EF核心:通过导航属性的子属性/字段(私有支持子字段)映射封装的集合导航属性

时间:2019-05-05 05:11:00

标签: collections entity-framework-core data-modeling ef-fluent-api navigational-properties


摘要


在Entity Framework Core [Code-First]中,是否可以通过该导航属性的私有(甚至公共)支持字段来映射该导航属性?本质上不是将其映射为:

modelBuilder.Entity<MyEntity>().HasMany(e => e.NavProperty)...

我们可以将其映射为(本质上,为了简洁起见,忽略反射或硬编码的字符串):

modelBuilder.Entity<MyEntity>().HasMany(e => e.NavProperty._Data)...

NavProperty视为导航属性并处理关系(即外键)吗?

我似乎无法弄清楚实现这种结果所需的Fluent API映射配置。我似乎记得在EF 6中这样做过,但可悲的是我再也没有该项目的源代码了。


详细信息


更全面的示例(C#、. NET Standard 2.2,Entity Framework Core 2.2 [Code-First]):

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }

    // ...

    public OrderCollection Orders { get; set; }

    public Customer()
    {
    }
}

public class Order
{
    public int OrderID { get; set; }
    public string OrderNo { get; set; }
    public bool Shipped { get; set; }

    // ...

    public Customer Customer { get; set; }

    public Order()
    {
    }
}

public class OrderCollection : IReadOnlyCollection<Order>
{
    private HashSet<Order> orders = new HashSet<Order>();

    public OrderCollection()
    {
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.orders.GetEnumerator();
    }

    public void Add(Order order)
    {
        this.orders.Add(order);
        // ... Other logic here
    }

    public bool Contains(Order order)
    {
        // ... Other logic here
        return this.orders.Contains(order);
    }
}

// The DbContext Class...
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    //... Other models setup / plumbing completed
    // How do we map the sub property / field??
    modelBuilder.Entity<Customer>().HasMany(customer => customer.Orders).WithOne(order => order.Customer);
}

该示例有些人为设计,但相当简单,只是为了快速入门:

本质上,OrderCollection是专用orders HashSet字段的包装,通过该字段,我们可以封装来自突变的真实数据,而通过所需的接口公开我们想要的行为。它还允许在最合适的时间处理域事件和/或其他问题,而调用者/所有者无需了解详细信息或不必在整个域模型中重复逻辑(即,帐单也将具有订单集合,质量也将如此)控制等)。它还可以防止依赖关系和横切关注点泄漏到主域模型中。


头脑风暴


我解决问题的一些想法包括:

1)让OrderCollection继承自HashSet<T>ReadOnlyCollection<T>之类的东西,然后重写我不想公开的方法。充其量看来,这似乎确实很hacky和脆弱(例如,我们通过怪异的伏都教徒魔术违反了“偏爱组成而非继承”的做法)。

2)只需转储“集合”的想法,并将项目的后备字段和所有逻辑放入违反DRY的实体模型中(其他模型将为{{1}使用相同类型的API }属性和SRP,因为现在我的Orders对象知道如何(例如如何实现的详细信息)向自身添加Customer。这是糟糕的设计。

3)通过自定义SQL /存储库/获取器和设置器/等手动处理导航属性?似乎EF应该在后台进行所有这些操作,而这可能是“重新发明轮子”。

我确实尝试过使用Order,但似乎它们是用于处理来回处理的数据库类型和.NET CLR类型的细微/深奥的问题的。也许是最好的解决方案,但是它需要特定类型的ValueConverter构造才能正常工作?

任何帮助或见识都受到赞赏!谢谢!

0 个答案:

没有答案