它的特殊之处在于,与其他方法不同,它首先访问内存并在 EntityFramework 跟踪的上下文对象中查找记录,然后才(如果没有找到)对数据库执行查询。如果上下文中有一个对象尚未存储在数据库中,该方法Find()仍将返回它(带有 state Added)。如果在那里或那里都找不到该条目,它将返回null。
生成的 SQL 查询:
SELECT TOP (2)
[Extent1].[Id] AS [Id],
[Extent1].[Title] AS [Title],
FROM [dbo].[Topics] AS [Extent1]
WHERE [Extent1].[Id] = @p0
值得注意的是,不是一条记录落入选择范围,而是两条SELECT TOP (2)。EF 在内部使用它来检查条目是否唯一。如果结果是多个具有相同主键的记录,EF 将抛出异常:
FirstOrDefault()、Find()、First() 始终首先尝试在数据上下文缓存中查找对象,如果在缓存中找不到对象,则再在数据库中查找。(阅读俄语版 Joseph Albahari 和 Ben Albahari 书“C# 6 IN A NUTSHELL”第 384 页)这是我运行的测试
using (var context1 = new DataContext())
{
//В данный момент у грузовика из context1 Title = "Грузовик"
var truck1 = context1.Trucks.FirstOrDefault();
using (var context = new DataContext())
{
//У этого грузовика из context2 по прежнему Title = "Грузовик"
var truck2 = context.Trucks.FirstOrDefault();
truck1.Title = "Грузовик обновленный";
context1.SaveChanges();
//В данный момент у грузовика из context1 Title = "Грузовик
//обновленный"
//этот цикл для задержки
for (int i = 0; i < 10000; i++)
{
var sum = Math.Sqrt(i);
}
//У этого грузовика из context2 по прежнему Title = "Грузовик", хотя в
//БД уже имеет Title = "Грузовик"
var truck3 = context.Trucks.FirstOrDefault(t4 => t4.Id == truck2.Id);
}
}
要搜索和获取实体对象,可以使用以下方法:
Find(),,,, .First()_FirstOrDefault()_Single()_SingleOrDefault()让我们考虑每一个:
该方法
Find()接受条目的主键作为参数。它的特殊之处在于,与其他方法不同,它首先访问内存并在 EntityFramework 跟踪的上下文对象中查找记录,然后才(如果没有找到)对数据库执行查询。如果上下文中有一个对象尚未存储在数据库中,该方法
Find()仍将返回它(带有 stateAdded)。如果在那里或那里都找不到该条目,它将返回null。生成的 SQL 查询:
值得注意的是,不是一条记录落入选择范围,而是两条
SELECT TOP (2)。EF 在内部使用它来检查条目是否唯一。如果结果是多个具有相同主键的记录,EF 将抛出异常:该方法
FirstOrDefault()将谓词作为参数,这使得不仅可以通过主键进行搜索,还可以通过任何条件进行搜索。例如,让我们查找具有以下内容的条目
Title == "test":FirstOrDefault()不像Find()每次对数据库执行查询时,不管上下文中是否有数据。如果来自数据库的记录与上下文中的记录不同,EF 将从上下文中返回该记录。如果记录不在数据库中,null即使在上下文中也会返回。生成的 SQL 查询:
在这里只查找一个条目
SELECT TOP (1)。如果发现有几条记录,它将返回第一条。该方法
First()类似FirstOrDefault(),但有一点不同 - 如果未找到该条目,将抛出异常:该方法
SingleOrDefault()类似FirstOrDefault()并返回一个实体对象,或null. 但是,该请求会生成类似于以下内容的方法Find():如果找到多个条目,它会抛出异常:
方法
Single()类似SingleOrDefault(),不同的是如果没有找到条目,会抛出异常:让我们总结一下:
什么时候使用
Find()?当需要按主键查找,需要全选实体数据时。
Find()如果记录已经加载到上下文中,则不会执行请求,因此在性能方面将优于所有其他方法。但是,如果您需要选择某些特定字段(例如,仅Id和Title),则必须使用其他方法。这同样适用于加载依赖数据(例如,通过Include())——Find()这是行不通的。什么时候使用其他方法?
如果您需要选择实体的某些字段或者您还需要加载依赖数据。使用哪些方法取决于个人需求:如果您需要检查条目是否存在(不抛出异常),以下方法是合适的
*OrDefault():如果您希望上下文包含数据的本地副本,您可以从那里获取它而无需查询数据库。为此,您需要访问
Local对象的属性DbSet:使用的来源:
这不是对作者问题的回答,而是对用户 tretetex 先前回答的修正。关于
FirstOrDefault()、Find()、First() 始终首先尝试在数据上下文缓存中查找对象,如果在缓存中找不到对象,则再在数据库中查找。(阅读俄语版 Joseph Albahari 和 Ben Albahari 书“C# 6 IN A NUTSHELL”第 384 页)这是我运行的测试
试验证实了这一点。