【发布时间】:2016-11-14 16:09:24
【问题描述】:
我需要在父实体中维护更新的属性,该属性属于下两层的子实体。我在 Asp.Net/MVC 应用程序中使用带有 Code First 和 DataAnnotations 的 EF6。
拥有这些实体:
public class Parent
{
[Key]
public int IdParent {get; set;}
// ...other properties
//The value of this property belongs to the Child table, two levels down.
public int Status { get; set; }
public Intermediate Intermediate { get; set; }
}
public class Intermediate
{
[Key, ForeignKey("Parent")]
public int IdIntermediate { get; set;}
// ... other properties
public Parent Parent { get; set; }
public Child Child { get; set; }
}
public class Child
{
[Key, ForeignKey("Intermediate")]
public int IdChild { get; set; }
//...other properties
public int Status { get; set; } // This is the property I need to keep updated in Parent Class
public Intermediate Intermediate { get; set; }
}
Parent 中的属性 Status 让用户快速查看在 Child 上执行的进程的结果,其中包含有关执行的详细信息。
我正在评估这些解决方案,如果您建议其中哪个更合适或其他更好的解决方案,我将不胜感激。
-
选项 1:在数据库中创建触发器以保持更新父表中的字段。此选项将在我的实体中生成更清晰的代码,但需要为触发器创建隔离迁移,因为它必须是 SQL 命令,并且难以维护。
public partial class AddUpdateTriggerOnChildMigration : DbMigration { public override void Up() { Sql("CREATE OR REPLACE TRIGGER [Child_UpdateStatus] FOR UPDATE ON dbo.Child..."); } public override void Down() { Sql("DROP TRIGGER [Child_UpdateStatus]"); } } -
选项 2:仅将字段保留在子表中,并在父实体上计算 Status 属性。但我不知道如何让它与 DataAnnotations 或 Fluent API 一起使用。
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public int Status { get; private set; } -
选项 3:将 NotMapped 设为属性 Parent.Status 并使用来自 Child 实体的代码填充它。这似乎是最糟糕的解决方案,并且也很难维护,并且当实体未附加到上下文时它将无法工作。
public class Parent { public int IdParent { get; set; } // ... [NotMapped] public int? Status { get { return this.Intermediate == null ? null : this.parent.Intermediate.Child.Status; } } public Intermediate Intermediate { get; set; } }
【问题讨论】:
-
你检查我的答案了吗?
-
是的@user449689。我选择了选项 1,即在隔离迁移中创建的子表上的触发器。现在它起作用了,因为我的内存中没有父实体。我将在未来的版本中引入领域事件来解决内存中的实体问题。谢谢!
-
非常感谢您的反馈,问候
标签: c# entity-framework code-first