一对多和递归关系 - 强制设置值

Posted

技术标签:

【中文标题】一对多和递归关系 - 强制设置值【英文标题】:One-To-Many AND Recursive relation - Force value to be set 【发布时间】:2014-09-26 03:12:48 【问题描述】:

环境

框架 4.5 实体框架 6(代码优先)

型号

MainEntity 一对多 ChildEntity 关系 ChildEntity 一对多递归 ChildEntity 关系

代码片段中的模型

public class MainEntity

    public long Id  get; set; 
    public virtual Collection<ChildEntity> ChildEntities  get; set;  


public class ChildEntity

    public long Id  get; set; 
    public MainEntity ParentMainEntity  get; set; 
    public virtual Collection<ChildEntity> ChildEntities  get; set;  

注意:一个 ChildEntity 只能再深一层 ChildEntities 作为 childeren。

问题

我能够坚持这个模型。这似乎工作正常。只有一个问题。当我存储具有父 ChildEntityChildEntity 时。 MainEntity_id 字段为 NULL,仅设置了 ParentChildEntityId。我希望始终设置 MainEntity_Id 字段的原因是用于性能查询。

如何强制 MAINENTITY_ID 字段始终在更深层次设置一个值?

【问题讨论】:

为什么不设置为[Required] 并使用对父ChildEntity 的引用来检索其MainEntity id,如果您为所有子实体执行此操作,则始终设置。 我尝试了这个想法,添加了对父 ChildEntity 的引用。存储方式与以前相同。当我在 ParentMainEntity 上附加 [Required] 标记时,我偶然发现 System.Data.Entity.Validation.DbEntityValidationException 出现“一个或多个实体的验证失败。有关详细信息,请参阅'EntityValidationErrors'属性。”作为消息。没有进一步的英特尔或堆栈跟踪可用于检查该问题。 @Stefan 好吧,验证异常是意料之中的。您需要一些机制来设置ParentMainEntity,最好是在您首先创建对象时。 顺便说一句,如果您需要某种方式从验证异常中获取一些有用的信息,请查看这篇文章:***.com/questions/15820505/… 但我 100% 确定 ParentMainEntity 正在被设置,我很生气,并通过单步调试来仔细检查设置的引用。我会看看你的链接@Stefan 【参考方案1】:

第一:

将外键排除在 POCO 之外,这给自己带来了麻烦。将MainEntityId 属性添加到ChildEntity 将使您能够将新ChildEntities 的关系设置为MainEntity

第二:

var newChild =new ChildEntity();
parentEntity.ChildEntities.Add(newChild);
parentEntity.ParentMainEntity.ChildEntities.Add(newChild);

应该取决于您加载实体的方式以及哪些实体已经或将要附加到 dbContext。

【讨论】:

【参考方案2】:

您只需要定义您需要的 MainEntity 和 ChildEntity 之间的关系。您可以通过两种方式进行:

    在 ChildEntity 中的 ParentMainEntity 属性上放置 [必需] 属性

    使用流畅的 api。在您的 DbContext 类中覆盖 OnModelCreating 方法并在其中放置代码:

    modelBuilder.Entity().HasRequired(e => e.ParentMainEntity).WithMany(e => e.ChildEntities);

我还想建议您将所有实体属性设为虚拟。当一切都是虚拟的,那么 ef 将创建自己的 DynamicProxy 类,而不是与您的实体类一起工作,这些类从您的类派生。它们将提供额外的跟踪功能,如果相关对象发生变化等,它们会自动更改导航属性的值。EF 似乎更好地处理它们。要为新创建的对象使用该功能,您需要使用 context.ChildEntities.Create() 方法而不是使用构造函数来创建它们。当然,由于这会增加对 ChildEntity 对象的约束,您可能会在将数据持久保存到 SaveChanges 中的 db 时遇到异常。如果上述更改是唯一的更改,那么您应用的更改很可能至少有一个 ChildEntity 对象没有分配 MainEntity 对象。

【讨论】:

以上是关于一对多和递归关系 - 强制设置值的主要内容,如果未能解决你的问题,请参考以下文章

一对多和一对多的关系 laravel

如何在 DynamoDB 中建模一对一、一对多和多对多关系

Hibernate映射关系:一对一对多和多对多

多表关系一对多和多对多

具有一对多和多对多关系的 JOOQ pojos

Hibernate自身一对多和多对多关系映射