EF Core支持具有协变类型参数的接口

时间:2017-10-26 11:30:22

标签: c# entity-framework domain-driven-design entity-framework-core domain-model

EF Core是否可以使用协变类型参数支持实体接口注册?

我理想的域名模型如下:

interface ICustomer<out TOrder>
{
    IReadOnlyCollection<TOrder> Orders { get; }
}

abstract class Order {}
class BusinessOrder : Order { }
class RetailOrder : Order { }

abstract class Customer<TOrder> : ICustomer<TOrder>
{
    HashSet<TOrder> _orders = new HashSet<TOrder>();

    public IReadOnlyCollection<TOrder> Orders => _orders;

    public void AddOrder(TOrder order)
    {
        _orders.Add(order);
    }
}

class BusinessCustomer : Customer<BusinessOrder> { }
class RetailCustomer : Customer<RetailOrder> { }

理想情况下,使用以下DbContext实现来支持我的模型:

class ShopContext : DbContext
{
    public DbSet<ICustomer<Order>> Customers { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ICustomer<Order>>()
            .HasDiscriminator<int>("CustomerType")
            .HasValue<BusinessCustomer>(1)
            .HasValue<RetailCustomer>(2);
    }
}

我理解每个具体的Customer类可以在DbSet<T>上声明为单独的DbContext,如下所示,以支持我的域模型:

DbSet<RetailCustomer> RetailCustomers { get; set; }
DbSet<BusinessCustomer> BusinessCustomers { get; set; }

但这不允许我针对所有类型的ICustomer<TOrder>编写单独的Linq查询,仅对派生的Customer数据库集类型本身进行编写,从而导致在结尾处合并多个结果集。

理想情况是针对上面的DbContext编写以下单个查询:

IList<ICustomer<Order>> customers = ctx.Customers.Where(c => c.Orders.Count > 0).ToList();

这种方法可以让我正确设计我的域模型,而不会使我的任何域规则失效。例如,只有我查询个人DbSet<Customer>的解决方法是:

abstract class Order { }
class BusinessOrder : Order { }
class RetailOrder : Order { }
class BusinessCustomer : Customer { }
class RetailCustomer : Customer { }

abstract class Customer
{
    public ICollection<Order> Orders { get; set; }
}

正如您所见,可以向BusinessOrder添加RetailCustomer,这会使我的域模型的规则无效。

这是一个专门关于EF Core支持协变类型参数的接口并将其注册到FluentAPI的问题。由于我的雇主的酌情要求,因为我已经模糊了真实世界的领域模型,因此构成与继承的论点是无关紧要的。

是否有任何第三方扩展可以与EF Core一起使用以满足我的域模型的要求,或者您建议重新设计?

0 个答案:

没有答案