【问题标题】:EF 4.0 Self-Tracking Entities, intended updates are being translated into insertsEF 4.0 自我跟踪实体,预期更新被转换为插入
【发布时间】:2011-04-11 19:38:54
【问题描述】:

假设以下方法存在于 WCF 服务中。 UI 检索到 Status 对象的实例,并使用此方法对服务进行后续调用。它没有像我期望的那样将状态分配给用户,而是尝试插入状态。我做错了什么?

void Method(Status status)
{
    //not sure if this is even needed, the status never changed
    context.Statuses.ApplyChanges(status);

    //get the first user from the database
    User user = context.Users.Where(u => u.Id = 1).First();

    //set user status to some existing status
    user.Status = status;

    //this throws an exception due to EF trying to insert a new entry
    //into the status table, rather than updating the user.StatusId column.
    context.SaveChanges();
}

【问题讨论】:

  • 是的,模式明智的用户有一个外键 User.StatusId,因此分配了 user.Status = status;
  • 我假设您发布的代码不是真正的代码,因为您的检索代码实际上并未运行查询。您需要在 where 子句之后添加 .First()(或 Single() 或任何您想要的)以实际检索用户实例。
  • 对不起,这就是我在记事本中输入示例所得到的。谢谢 KallDrexx。

标签: c# asp.net entity-framework entity-framework-4 self-tracking-entities


【解决方案1】:

问题是您正在使用附加用户。当 STE 附加到上下文时,它的行为方式与任何其他实体完全相同。更何况它的自我跟踪机制没有被激活。因此,您必须先将状态附加到上下文,然后再将其设置给用户,否则它将被跟踪为必须插入的新实体:

void Method(Status status)
{
    User user = context.Users.Where(u => u.Id = 1).First();

    context.Attach(status);
    user.Status = status;

    context.SaveChanges();
}

【讨论】:

    【解决方案2】:

    试试这个:

            using (Entities ctx = new Entities())
            {
                ctx.Statuses.Attach(status);
    
                ObjectStateEntry entry = ctx.ObjectStateManager.GetObjectStateEntry(status);
                entry.ChangeState(EntityState.Modified);
    
                //get the first user from the database
                User user = ctx.Users.Where(u => u.Id = 1);
    
                //set user status to some existing status
                user.StatusID = status.StatusID;
    
                ctx.SaveChanges();
            }
    

    如果您有兴趣,这里是tutorial on CRUD with Entity Framework

    【讨论】:

    • BrandonZeider,但如果我实际上从未修改过 Status 对象,为什么还要将其设置为已修改?从逻辑上讲,我希望 EF 知道该对象实际上是事先检索到的并且没有被修改,因此不需要任何类型的更新。
    • 另外,为什么我需要附加实体,这不是 STE 的全部意义在于我不需要手动附加它们并设置它们的状态吗?
    • 啊,那你就不用管它了。只需获取您的用户,将 statusID 设置为 status.StatusID 并调用 SaveChanges()。如果要将更改保存到状态实体​​,只需将实体状态更改为已修改。我被你对 ApplyChanges() 的调用吓跑了……
    • 我不明白为什么这会有所作为。我知道你的建议应该有效,但它仍然没有向我解释为什么我得到的是插入而不是更新。
    • 我的猜测是因为您将 user.Status 设置为等于未附加的状态对象。首先尝试附加状态,看看它是否插入了新记录。如果没有,那就是发生了什么。
    【解决方案3】:

    必须写一个答案,因为我还不能评论另一个答案(rep score 这有点奇怪,但我明白为什么会这样]因为我想要为@Ladislav 的回答增加一些清晰度。

    来自 WCF 调用的 Status 对象并非来自您用于查找 User 对象的同一 context,因此跟踪代码未与该上下文相关联。这就是为什么附加它可以让您在不考虑 status 是需要插入数据库的新实体的情况下保存分配的原因。

    【讨论】:

    • 我明白你在说什么,但我一直认为带有 STE 的 ApplyChanges() 也会将实体附加到上下文中,也许我错了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多