【问题标题】:EF4.1 Code First Add Entity with Related EntityEF4.1 代码优先添加具有相关实体的实体
【发布时间】:2011-08-09 07:29:15
【问题描述】:

我使用的是 EF4.1 代码优先。我无法获得非常简单的插入来保存相关的实体 ID。生成的 SQL 始终为任何相关实体插入 NULL。示例代码如下。谁能看到我在这里做错了什么?它确实正确插入了非实体属性,例如字符串。此外,我在 DB 初始化程序类中有类似的代码来播种测试数据,它似乎工作正常。

        using (var ctx = new DataContext())
        {
            ctx.Users.Attach(existingUser);

            // create item and add to context
            var newItem = new MyItem();
            ctx.MyItems.Add(newItem);

            // set related entity
            newItem.CreatedBy = existingUser;

            ctx.SaveChanges();
        }

【问题讨论】:

    标签: c# entity-framework entity-framework-4.1 ef-code-first


    【解决方案1】:

    您的代码应该使用您的DbContext 的默认配置。它不起作用的一种可能解释是您禁用了自动更改检测,例如,如果您在上下文的构造函数中有类似的内容:

    public DataContext()
    {
        this.Configuration.AutoDetectChangesEnabled = false;
    }
    

    在这种情况下,在您将新项目添加到上下文后,EF 不会检测到导航属性 newItem.CreatedBy 的更改。 (如果未禁用更改检测,SaveChanges 将检测到最后一次更改。)

    您可以更改代码,以便在将新项目添加到上下文之前设置导航属性:

    using (var ctx = new DataContext())
    {
        ctx.Users.Attach(existingUser);
    
        // create item and add to context
        var newItem = new MyItem();
    
        // set related entity
        newItem.CreatedBy = existingUser;
    
        ctx.MyItems.Add(newItem);
    
        ctx.SaveChanges();
    }
    

    这应该在有和没有自动变化检测的情况下工作。

    【讨论】:

    • 我确实将更改检测设置为 false。并且如上所述移动代码解决了这个问题。谢谢您的帮助。我想还必须有某种方法将属性标记为已更改?更新现有实体的情况如何。
    • 它似乎在做这样的事情:ctx.Entry(existingItem).State = EntityState.Modified 是附加现有实体的解决方案。
    • @Barry:请注意,手动将状态设置为 Modified 会导致 full 更新 SQL 语句:All 属性将发送到服务器,无论他们是否真的改变了。通常从数据库中检索原始对象并将更改的属性合并到其中会更好(性能方面)。 EF 将跟踪这些更改并仅发送具有真正更改的属性的更新命令。
    • 很多时候我知道在保存之前可能会发生什么变化。有没有办法手动将单个属性标记为已修改?
    • @Barry: Yes: dbContext.Entry(entity).Property(e => e.SomeProperty).IsModified = true; 它将附加的entity 中的SomeProperty 标记为已修改。
    【解决方案2】:

    试试这个:

    using (var ctx = new DataContext())
    {
        ctx.Users.Attach(existingUser);
    
        // create item and add to context
        var newItem = new MyItem();
        ctx.MyItems.Add(newItem);
    
        // set related entity
        newItem.CreatedBy = existingUser;
    
        // Added
        ctx.ObjectStateManager.ChangeObjectState(newItem.CreatedBy, EntityState.Added);
    
        ctx.SaveChanges();
    }
    

    如果这不起作用,请更改以下行:

    ctx.ObjectStateManager.ChangeObjectState(newItem.CreatedBy, EntityState.Modified);

    添加了 1 行...希望对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      相关资源
      最近更新 更多