【问题标题】:EF 4.1 SaveChanges not updating navigation or reference propertiesEF 4.1 SaveChanges 不更新导航或参考属性
【发布时间】:2011-04-01 18:14:20
【问题描述】:

我首先使用代码,可以毫无问题地添加记录。数据库已正确创建并且已播种没有任何问题。但是在我的 Edit 操作中调用 SaveChanges() 只会更新实体,而不是任何导航或引用属性。

我的模型的简化版本:

public class Contact : IMyBaseObject
{
    public Contact()
    {
       this.Delete = false;
       this.ContactTypes = new HashSet<ContactType>();
    }

    public int Id {get; set;}

    public string Name {get;set;}

    public bool Delete {get;set;}

    public virtual ICollection<ContactType> ContactTypes { get; set; }

    public virtual USState USState { get; set; }

}

public class ContactType : MyBaseObject
{
    public ContactType()
    {
    }

    public int Id {get; set;}

    public string Name {get;set;}

    public virtual ICollection<Contact> Contacts {get;set;}
}

public abstract class Territory : MyBaseObject
{
    public int Id {get; set;}

    public string Name {get;set;}

    public string Code {get;set;}
}

public class USState : Territory
{
    public USState()
    {
    }

    // Navigation properties
    public virtual ICollection<Contact> Contacts { get; set; }
}

我不会包含代码,但我确实有一些自定义模型绑定正在进行。我的编辑操作(使用 MVC 3)没有填充 ContactType 或 USState 属性。绑定正确地返回了一个完全填充的 Contact 对象,该对象具有来自表单的正确值。

如果我正确理解 EF 4.1,我只需执行以下操作即可在保存联系人对象时将更改持久保存到数据库:

if(ModelState.IsValid)
{
    context.Entry(contact).State = EntryState.Modified;
    context.SaveChanges();
}

但是,当我这样做时,只会更新原始属性。在上面的例子中我遗漏了一些东西:我正在使用一个事务,一个 try catch 块,并检查它是否是一个新记录。

我使用了 SQL Profiler,可以确认 ContactType 和 Territory 表的更新查询没有发送到数据库服务器。

我的导航和参考属性的状态属性已修改,但我也尝试手动设置:

    context.Entry(contact).Collections("ContactTypes").EntityEntry.State = EntityState.Modified;
    context.Entry(contact).Reference("USState").EntityEntry.State = EntityState.Modified;

我可能弄错了,但我很确定我的代码在 CTP5 下运行。

有什么想法吗?在这一点上,我不确定我应该如何调试它。

谢谢,史蒂夫

【问题讨论】:

  • 这个问题在过去 21 小时内被第三次问到。以下是以前的:stackoverflow.com/questions/5506116/…stackoverflow.com/questions/5507596/…
  • 有趣。我应用了您在其他问题中描述的解决方案,但它对我不起作用。没有错误,但没有更新查询被发送到数据库。我想我会尝试删除导航/参考属性并尝试将它们重新添加。
  • Steve,MyBaseObject 是什么,我在您的帖子中没有看到该类的代码。我假设它是一个类,因为它不遵循作为接口的约定。其次,您可能希望为 DbContext 实现一个非常基本的存储库模式,因为这将有助于使您的代码更有条理并为您提供一定程度的抽象。
  • 您的其他代码非常相关,我建议您将其包含在内。特别是在保存之前如何绑定关系/导航属性
  • @CodeJammr 我的意思是 IMyBaseObject。我会解决问题

标签: entity-framework entity-framework-4.1


【解决方案1】:

试试这个:

  context.Entry(contact.USState ).State = EntityState.Modified; //////

【讨论】:

    【解决方案2】:

    假设您的 DAL 对象/集合来自实体框架,请执行此操作;

    Contact.ContactTypes.Load();

    这将从底层源刷新相关的 coltactTypes 列表。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      提供的代码可能还不够。更好地查看代码中导航属性是如何添加到代码中的。 因为即使父类被标记为已修改,并不意味着相关的导航属性也被标记为已添加或已修改。 最快的方法是在调用 .SaveChanges 的地方打开调试器,然后查看上下文变量,查看“Local”属性,然后导航属性是否存在,以及它们的模态状态是否被添加或修改,然后告诉我们需要做什么会容易得多。

      【讨论】:

        【解决方案4】:

        我确信更多的代码将有助于更好地解决问题,尤其是用于模型绑定的代码。但我认为您已经熟悉的一件事是您需要访问这些导航属性(不知何故),以便 EF 能够自动加载它们。因为您将导航属性标记为虚拟,您允许 EF 创建代理并覆盖您的导航属性以允许延迟加载。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-11-10
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多