0

我有这些 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);
}

令我惊讶Update的是,如果我只更新BaseorDerived类,它实际上是有效的。但是,当我尝试更新一对多关系时,事情变得很糟糕。我找到了有关如何在 EF4中更新一对多实体的教程。我真的希望 EF 比这更聪明,我的意思是我必须手动完成......这与 EF 中的其他所有内容都不同。

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

显然,我一定是做错了什么,或者与其他人如此不同,因为我无法找到任何有用的东西。无论如何,EF5 没有对此进行改进吗?关于如何解决这个问题的任何建议?

4

1 回答 1

0

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

于 2013-11-09T21:24:29.070 回答