EF Core实体的相等性

4
抱歉,如果这是一个愚蠢的问题,请原谅。我的ORM大多数经验不是EF,而且在线搜索会得到很多错误的结果。好像“参考”对不同的人有不同的含义……
如果我写出如下代码:
using (var db = new DbContext())
{
    var entity1 = await db.Foos.FirstOrDefaultAsync(x => x.Id == 1);
    var entity2 = await db.Foos.FirstOrDefaultAsync(x => x.Id == 1);
    return entity1.Equals(entity2);
}

这将返回true。由于我的实体是引用类型,底层的Equals应该是一个Object.ReferenceEquals()调用。

我想知道的是,这是否可靠,即在上下文中表示特定数据库记录的任何实体都将具有相同的引用,或者它是否可能“掉出”缓存,按需重新加载并具有新引用,就像在某些不太成熟的ORM中发生的那样?如果一个实体作为另一个实体集合的一部分加载,它仍然是同一个对象吗?是否有规则/设置来管理此行为?


当您使用 Find 时,会按优先顺序发生三件事情:1)EF 在本地缓存中查找对象,2)EF 在已添加的对象中查找,3)EF 从数据库加载数据。 - JohnyL
1
除非这是已记录的行为(我认为不是),否则我不会依赖它。而且有人总是可以覆盖Equals... - bornfromanegg
@JohnyL 我猜应该是这样,但本地缓存有多健壮?它能够在数据库上下文的生命周期内持久存在吗?还是会一直保留直到需要空间或记录被认为已过期?如果我关心唯一性,我想知道它有多可靠。 - Jeremy Holovacs
4
除了Non-Tracking Queries之外,它是有保证的(尽管我找不到文档)。实际上,这是许多问题的根源,会出现“另一个具有相同关键字的实体已由上下文跟踪”异常。此外,EF对跟踪使用引用相等性进行了强制,因此即使对象重写了Equals,它们仍然检测相等的引用而不是自定义相等性。或者以你的例子为例,它们在内部始终使用ReferenceEquals(entity1, entity2)而不是entity1.Equals(entity2) - Ivan Stoev
我错过了EF Core标签。我在之前的评论中写的所有内容仍然适用。这在查询工作原理跟踪与非跟踪查询中有所解释 - 请注意“无跟踪查询仍在执行查询时执行标识解析”中的“标识”一词。 - Ivan Stoev
1个回答

2

正如@IvanStoev在评论中指出的那样,参考一致性是EF的设计核心,因此数据库中的同一对象应始终引用数据库上下文中的同一对象...至少在您所在的特定数据库上下文范围内。 如果您正在处理多个数据库上下文,则可能会有所不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接