考虑以下内容......
数据库:
Table: XFUNCTION
-------------
|ID |NAME |
-------------
|1 |F1 |
-------------
|2 |F2 |
-------------
Table: XSYSTEM
-------------
|ID |NAME |
-------------
|3 |S1 |
-------------
|4 |S2 |
-------------
Table: FUNCTION_HAS_SYSTEM
--------------------------------
|ID |SYSTEM_ID |FUNCTION_ID |
--------------------------------
|5 |3 |1 |
--------------------------------
|6 |3 |2 |
--------------------------------
|7 |4 |1 |
--------------------------------
|8 |4 |2 |
--------------------------------
代码:
var dbContext = new EFContext();
var functions = dbContext.XFUNCTION; //Count == 2
var systems = new List<XSYSTEM>();
foreach(var func in functions)
{
foreach(var sys in func.systems) //Count == 2
{
if (!systems.Contains(sys))
systems.Add(sys);
}
}
Assert.IsTrue(systems.Count == 4);
Output: systems.Count == 2 not 4
只要我没有覆盖Equals()
和GetHashCode()
我就预计4个系统不会2 ... 有人可以告诉我为什么EF这样做,是否可以预料到?我该如何防止这种行为?
这个问题的原因是,当我尝试在其中一个函数中操作系统对象时,没有执行SaveChange()
。在另一个函数中,系统对象也会发生同样的事情。我知道它们是数据库中的相同系统,但我希望它们是它们自己的对象,而不是在实体中共享。
答案 0 :(得分:0)
Object.Equals()返回true,因为EF返回相同的对象! EF将查询的实体保留在内存中并默认重用,除非您禁用更改跟踪。
有许多方法可以停用更改跟踪:
1)使用.AsNoTracking()
var xfunctionSet = dbContext.XFUNCTION.AsNoTracking();
Assert.AreSame(xfunctionSet.First(), xfunctionSet.First()); //fails
2)更改MergeOption
但是如果你只想计算FUNCTION_HAS_SYSTEM中的总记录数,那就
dbContext.FUNCTION_HAS_SYSTEM.Count()