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一起使用以满足我的域模型的要求,或者您建议重新设计?