如何为多父类型的子场景编写EF代码第一映射

本文关键字:EF 代码 映射 父类 类型 | 更新日期: 2023-09-27 18:17:24

我有4个类。供应商、客户、员工和地址。前三种类型中的任何一种都可以有"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);
    }
}

如何为地址的父属性写映射?或者有更好的方法/设计来实现这种场景?

如何为多父类型的子场景编写EF代码第一映射

您希望EF如何在数据库中解决这样的映射?将地址。ParentId列引用客户、供应商或雇员的主键?

如果你去掉从Address到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"));
}

如果Employee, Customer和Supplier不共享父实体(类)并且不遵循继承映射,则不能这样做。您的地址必须与@olivehour提到的每个相关实体有单独的关系。

来自OP的评论:

我不想每个Parent类型都有很多Address类。不,我不想查询/导航从地址到父。

在你的领域逻辑或用户工作流中是否有一些东西会使多个父母共享相同的地址成为一个真实的场景?例如,地址共享的事实是否会以一种重要的方式显示在UI中,除非他们都面对面地登录和交换信息?

如果不是,我不确定两个相同的地址是否共享相同的ID是否真的重要,我不确定潜在的数据重复是否重要。

在这种情况下,我推荐KISS。

创建三个独立的映射表,不需要任何继承,并调用它完成:)

SupplierToAddressMap:
SupplierId  AddressId
CustomerToAddressMap:
CustomerId  AddressId
EmployeeToAddressMap:
EmployeeId  AddressId