Как написать EF Code first mapping для сценария Child with Many Parent Types - PullRequest
1 голос
/ 11 декабря 2011

У меня есть 4 класса. Поставщик, клиент, работник и адрес. Любой из первых 3 типов может иметь «n» количество адресов. Итак, классы выглядят так:

class Address 
{
    int Id { get; set; }
    int ParentId { get; set; }  // NOTE: This is the FK.
    IAggregateRoot Parent { get; set; } // EXAMPLE: Supplier, Customer, Employee ..

    // rest of the address fields.
}

class Supplier : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the supplier details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

class Customer : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the customer details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

class Employee : IAggregateRoot
{
    int Id { get; set; }
    virtual List<Address> Addresses { get; set; }

    // rest of the employee details.

    AddAddress(Address address)
    {
        address.Parent = this;
        address.ParentId = this.Id;

        Addresses.Add(address);
    }
}

Как написать сопоставление для атрибута родительского адреса? Или лучший подход / дизайн для такого рода сценария?

Ответы [ 3 ]

2 голосов
/ 11 декабря 2011

Как вы ожидаете, что EF решит такое отображение в БД? Будет ли столбец Address.ParentId ссылаться на первичный ключ клиента, поставщика или сотрудника?

Возможно, вы сможете сделать это, если избавитесь от навигации от адреса к IAggregateRoot. Возможно, попробуйте это:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Employee>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("EmployeeId"));
    modelBuilder.Entity<Supplier>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("SupplierId"));
    modelBuilder.Entity<Customer>.HasMany(p => p.Addresses).WithOptional()
        .Map(d => d.MapKey("CustomerId"));
}
0 голосов
/ 11 декабря 2011

Из комментариев на ОП:

Я не хотел иметь много классов адресов для каждого родительского типа. Нет, я не хочу, чтобы запрос / переход от адреса к родителю.

Есть ли в вашей доменной логике или рабочих процессах что-то, из-за чего несколько родителей делят один и тот же адрес реальным сценарием? Например, будет ли тот факт, что адреса общего доступа когда-либо будут отображаться в пользовательском интерфейсе важным способом, если они одновременно не будут входить в систему и обмениваться информацией лицом к лицу?

Если нет, я не уверен, что это действительно имеет значение, если два идентичных адреса имеют один и тот же идентификатор или нет, и я не уверен, что потенциальное дублирование данных имеет значение.

В этом случае я рекомендую KISS.

Создайте три отдельные таблицы сопоставления, не занимайтесь наследованием и назовите это готовым:)

SupplierToAddressMap:
SupplierId  AddressId

CustomerToAddressMap:
CustomerId  AddressId

EmployeeToAddressMap:
EmployeeId  AddressId
0 голосов
/ 11 декабря 2011

Если Сотрудник, Клиент и Поставщик не разделяют родительскую сущность (класс) и не следуют отображению наследования, вы не сможете этого сделать. Ваш адрес должен иметь отдельное отношение для каждой связанной сущности, как упомянуто @olivehour.

...