【问题标题】:Should I keep foreign keys in sync with references when using POCOs使用 POCO 时我是否应该使外键与引用保持同步
【发布时间】:2012-08-30 07:09:33
【问题描述】:

我看到很多关于首先使用 EF 代码和 POCO 的示例,这些示例显示如下:

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogId { get; set; }
    public virtual Blog Blog { get; set; }
}

现在,查看Blog 属性。不应该是这样吗:

private Blog blog;
public virtual Blog Blog 
{ 
    get
    {
        return blog;
    } 
    set
    {
        blog = value;
        if (blog != null)
        {
            BlogId = blog.BlogId;
        }
    } 
}

我的意思是,既然你已经用外键“污染”了你的模型,你不应该至少让它与参考保持同步吗?或者,无论如何在读取数据时都不应该依赖BlogId(例如,您想知道特定的BlogId 是否在列表中)。或者DbContext(如KeepForeingKeysPropertiesSyncronizedWithReferences)上可能有一个神奇的属性对我有这种作用,而我是唯一对此感到担忧的可悲程序员?还是我偏执? (另外,对不起我的英语不好)

编辑 很抱歉——这真是一个愚蠢的问题。 Stefan 是对的,EF 确实为您做到了这一点。我没有看到这个,因为我传递的引用加载了AsNoTracking()。只有在这种情况下,您才会有一个带有 ID 的引用,并且外键字段将为 0。只要您传递一个已经在上下文中的引用,它应该可以工作。

【问题讨论】:

  • 不了解 EF,但如果您使用 NHibernate,您根本不会放入 BlogId 属性。
  • 我认为有可能使用 BlogId 很好,所以我不需要博客引用并且仍然可以保存关联。我只是对保持同步感到困惑-对我来说,这看起来很明显,但我从未见过有人这样做,所以也许我错了:/

标签: entity-framework entity-framework-4.1 ef-code-first entity-framework-5


【解决方案1】:

您本身不需要执行此操作,EF 会为您执行此操作。
如果您设置独立关联属性,EF 将同步外键属性以反映您的更改,反之亦然。请注意,它不会立即自动发生,我认为这是在调用 SaveChanges 后发生的,但我不确定。
如果您想知道为什么有些人使用外键属性:它在分离的应用程序(如 Web 应用程序)中更方便。当您需要扩展应用程序时,它还有助于提高性能(在某处最近的 MS 博客文章中阅读此内容)。
基本上,只有在混合和匹配时,您才需要自己执行此操作;当您在一种方法中使用独立关联属性而在另一种方法中使用外键属性时。

【讨论】:

    【解决方案2】:

    首先生成数据库代码。

    您似乎选择了“是”,否则您将收到以下错误。

    发生了参照完整性约束违规:属性 定义引用约束的值不一致 关系中的主体对象和依赖对象之间的关系。

    Principle 是 Post 对象,dependent 是 Blog 对象。

    当您尝试将未分配的上下文无关 POCO 附加回上下文时 EF 4.1 DBContext:

    using (TransactionScope scope = new TransactionScope())
    using (ITAMdbContext db = new ITAMdbContext())
    {
       db.Entry(post).State = System.Data.EntityState.Unchanged; // error here
       db.Entry(post).State = System.Data.EntityState.Modified; 
       db.SaveChnages();
    

    这个错误被解决了..

    using (TransactionScope scope = new TransactionScope())
    using (ITAMdbContext db = new ITAMdbContext())
    {
       post.BlogId = post.Blog.BlogId;
     // fix the broken FK value, EF will not do this for
     // you, it does not know if post.BlogId or the post.Blog.BlogId should be chosen. 
    
       db.Entry(post).State = System.Data.EntityState.Unchanged; 
       db.Entry(post).State = System.Data.EntityState.Modified; 
       db.SaveChnages();
    

    如果您的 POCO 对象不是自动生成的,那么按照您的方式进行操作是有效的。

    您将 post 设置为 Unchanged 然后将其设置为 Modified 的原因是因为在对象上设置的第一个 Entry().State 会将相同的状态级联到所有子对象!可怕,但这就是它的工作方式。 然后当你再次调用它时,它只会修改 post 对象。这会阻止修改或添加子对象。

    编辑:这不再需要,它为您完成

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多