实体框架 (POCO) +单元测试=集合被修改异常
我有一个使用 EF POCO 访问数据的应用程序。一切都很好,但单元测试存在一个问题。想象两个相关的类:
public class Brother
{
public virtual Sister Sister { get; set; }
}
public class Sister
{
public virtual ICollection<Brother> Brothers { get; set; }
}
这里的问题是,如果我们有一个 Brother 实例,并将相关实体设置为其他实体,则 ObjectContext.DeleteObject() 仅在单元测试项目中抛出常见的“Collection was generated”(单元测试是由内置 VS 框架完成)。该问题不会
出现在项目本身中。失败的示例代码:
public void TheTestThatFails()
{
Brother bro = MyContextInst.CreateObject<Brother>();
Sister sis = MyContextInst.CreateObject<Sister>();
sis.Brothers.Add(bro);
MyContextInst.AddToBrothers(bro);
MyContextInst.AddToSisters(sis);
MyContextInst.SaveChanges();
// The following will throw a "Collection was modified" ex
MyContextInst.DeleteObject(sis);
// Yet if we disconnect the object graph everything is fine
// The following will work fine:
bro.Sister = null;
MyContextInst.DeleteObject(sis);
}
这是从哪里来的?据我所知,环境是完全相同的(我已经开始实际进行单元测试,并且该项目使用相同的数据库,相同的用户,相同的一切)。
为什么EF无法处理单元测试项目中的对象图?为什么它只在单元测试中失败?...我完全困惑。
- 请注意,没有用户代码提及集合 - 异常必须来自 EF 代码内部?..
编辑:调查后: * 如果集合至少是 1-many,就会发生这种情况(编辑代码) * 似乎级联删除更安全的方法是先删除子对象(Brothers),然后清除父对象(Sister)的集合,然后才从上下文中删除它,因为 EF 本身内部有一些东西尝试连接实体并从其他实体中删除内容。现在这个问题对我来说已经解决了。
I have an app that uses EF POCO for accessing data. Everything works great, yet there is one problem with unit testing. Imagine two related classes:
public class Brother
{
public virtual Sister Sister { get; set; }
}
public class Sister
{
public virtual ICollection<Brother> Brothers { get; set; }
}
The problem here is that if we have an instance of Brother with the related entity set to some other entity then ObjectContext.DeleteObject() throws the common "Colletion was modified" ONLY in the unit test project (unit testing is done by the build-in VS framework). The problem does not
occur in the project itself. Example code that fails:
public void TheTestThatFails()
{
Brother bro = MyContextInst.CreateObject<Brother>();
Sister sis = MyContextInst.CreateObject<Sister>();
sis.Brothers.Add(bro);
MyContextInst.AddToBrothers(bro);
MyContextInst.AddToSisters(sis);
MyContextInst.SaveChanges();
// The following will throw a "Collection was modified" ex
MyContextInst.DeleteObject(sis);
// Yet if we disconnect the object graph everything is fine
// The following will work fine:
bro.Sister = null;
MyContextInst.DeleteObject(sis);
}
Where does this come from? As far as I can tell the environment is exactly the same (I have come to actually making unit tests and the project use same DB, same user, same everything).
Why cannot EF handle the object graph in the unit test project? Why does it ONLY fail in unit testing?.. I am completely puzzled.
- Note how there is no user-code mentioning collections - the exception must come from within the EF code?..
EDIT: After investigation:
* this happens if the collection is at least 1-many (edited the code)
* it seems that the more safe way of cascade deleting would be to remove the children objects first (Brothers), then clear the collection of the parent (Sister) and only after that delete it from the context as there is something inside EF itself that tries to connect the entities and removes stuff from something else. The question is solved for me at the moment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如其他人所说,单元测试不是为了测试 EF,而是为了测试业务规则。您能否提供有关您正在尝试做什么的更多信息,我们可以为您提供帮助。
As others have said unit test isnt to test EF, should keep it to testing business rules. Can you provide more info on what your are trying to do, and we can help you out.
经过调查: * 如果集合至少是 1-many(编辑代码),就会发生这种情况 * 似乎级联删除更安全的方法是先删除子对象(兄弟),然后清除父对象的集合(姐妹)只有在那之后才将其从上下文中删除,因为 EF 本身内部有一些东西试图连接实体并从其他东西中删除东西。现在这个问题对我来说已经解决了。
同样,这是 EF 中的一个错误。我只是找不到 Connect 问题的链接,但它就在那里。因此,作为任何人的解决方案 - 只需在删除之前尝试手动断开对象图的连接即可。那么应该没问题。
After investigation: * this happens if the collection is at least 1-many (edited the code) * it seems that the more safe way of cascade deleting would be to remove the children objects first (Brothers), then clear the collection of the parent (Sister) and only after that delete it from the context as there is something inside EF itself that tries to connect the entities and removes stuff from something else. The question is solved for me at the moment.
Again, this was (or is) a bug in EF. And I just cannot find the link to the Connect issue, but it was there. So as a solution for anyone - just try manually disconnecting object graphs before deleting. Then it should be fine.