使用One-to-Many子级更新派生实体

时间:2013-08-07 20:50:42

标签: c# entity-framework-5 one-to-many table-per-type

我有这些POCO类,它们使用Fluent API和TPT(每类型表)策略进行映射。

public class Base 
{
   ...
}

public class Derived : Base
{
   ...
   public virtual ICollection<Foo> Foos {get; set;} // One-to-Many
}

public class Foo
{
   ...
   public virtual ICollection<Bar> Bars {get; set;} // One-to-Many
}

public class Bar
{
   ...
}

我的存储库看起来像这样。

public class Repo
{
   public void Update(Base item)
   {
      using (var ctx = new DbContext())
      {
         ctx.Entry(item).State = EntityState.Modified;
         ctx.SaveChanges();
      }
   }
}

动作:

public void DoStuff()
{
   Derived item = repo.GetById(1);
   item.SomeProp = "xyz"; // new value
   item.Foos = GenerateFoosWithBars(); // change children
   repo.Update(item);
}

如果我只更新UpdateBase类,那么Derived实际上是有效的。然而,当我尝试更新一对多关系时,事情变得丑陋。我在EF4中找到了tutorial on how to Update One-to-Many Entities。我真的希望EF比这更聪明,我的意思是我必须手动完成......这与EF中的其他所有内容都不同。

所以我开始尝试使用Entry因为我希望它是通用的(能够使用Base更新任何Entry.OriginalValues派生类)以避免必须自己编写查询。但现在狗屎真的击中了粉丝! Entry.OriginalValues失败,并说明DbSet<Derived>不存在。这是完全正确的,但事实并非如此。但它不应该通过继承将Derived映射到DbSet<Base>

显然,我必须做错事或与其他人不同的事情,因为我无法找到有关此事的任何有用信息。无论如何,EF5还没有改进吗? 关于如何解决这个问题的任何建议?

1 个答案:

答案 0 :(得分:0)

首先,我认为在存储库中不需要Update方法,因为EF会跟踪更改并在您在上下文中调用SaveChanges()时应用。 其次,问题可能是你在你做的时候为Foos poperty分配一个新的集合:item.Foos = GenerateFoosWithBars();您不应该这样做,因为当EF实现Derived类型的对象时,它实际上返回一个代理,该代理覆盖虚拟Foos集合以使用它跟踪的特殊类型的延迟加载集合。如果您指定了自己的不同集合,则不会绑定到上下文。 (我认为EF不会很好地处理这个问题)。你应该做的是修改集合项而不是集合本身!希望它有所帮助!

相关问题