【问题标题】: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,最好是在您首先创建对象时。
  • 顺便说一句,如果您需要某种方式从验证异常中获取一些有用的信息,请查看这篇文章:stackoverflow.com/questions/15820505/…
  • 但我 100% 确定 ParentMainEntity 正在被设置,我很生气,并通过单步调试来仔细检查设置的引用。我会看看你的链接@Stefan

标签: c# entity-framework ef-code-first .net-4.5 entity-framework-6


【解决方案1】:

第一:

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

第二:

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

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

【讨论】:

    【解决方案2】:

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

    1. 在 ChildEntity 中的 ParentMainEntity 属性上放置 [必需] 属性
    2. 使用流畅的 api。在您的 DbContext 类中覆盖 OnModelCreating 方法并在其中放置代码:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-27
      • 2020-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多