c# - 当我们在 Entity Framework Core 中拥有主键时,我们是否应该始终使用 .Find() 而不是 .FirstOrDefault() ?

标签 c# linq asp.net-core entity-framework-core

https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/details?view=aspnetcore-3.0

在 Microsoft 文档示例中,.FirstOrDefaultAsync()用于DetailDelete GET ;.FindAsync()用于DeleteConfirmed .
我想知道这是为什么?

最佳答案

根据reference source DbSet.Find如果已在 DbContext 中获取具有相同 keyValues 的对象,则不会访问数据库:

///     Finds an entity with the given primary key values.
///     If an entity with the given primary key values exists in the context, then it is
///     returned immediately without making a request to the store. 
public abstract object Find(params object[] keyValues);

FirstOrDefault,类似的函数会调用IQueryable.GetEnumerator() ,它将向 IQueryable 询问提供者的接口(interface) IQueryable.GetProvider()然后调用IQueryProvider.Execute(Expression)获取表达式定义的数据。
这将始终访问数据库。

假设您有学校和学生,这是一种简单的一对多关系。您还有一个更改学生数据的程序。
Student ChangeAddress(dbContext, int studentId, Address address);
Student ChangeSchool(dbContext, int studentId, int SchoolId);

您在程序中有这个,因为这些程序将检查更改的有效性,可能伊顿学生不允许住在牛津校区,并且可能有些学校只允许特定年龄的学生。

您有以下代码使用这些过程:
void ChangeStudent(int studentId, Address address, int schoolId)
{
    using (var dbContext = new SchoolDbContext())
    {
        ChangeAddress(dbContext, studentId, address);
        ChangeSchool(dbContext, studentId, schoolId);
        dbContext.SaveChanges();
    }
}

如果 Change... 函数将使用 FirstOrDefault()那么您将丢失其他过程所做的更改。

但是,有时您希望能够重新获取数据库数据,例如,因为其他人可能已经更改了数据,或者您刚刚所做的某些更改无效
Student student = dbContext.Students.Find(10);
// let user change student attributes
...

bool changesAccepted = AskIfChangesOk();
if (!changesAccepted)
{    // Refetch the student.
     // can't use Find, because that would give the changed Student
     student = dbContext.Students.Where(s => s.Id == 10).FirstOrDefault();
}

// now use the refetched Student with the original data

关于c# - 当我们在 Entity Framework Core 中拥有主键时,我们是否应该始终使用 .Find() 而不是 .FirstOrDefault() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58773913/

相关文章:

c# - 用于对不同属性中的不同对象进行排序的通用 IComparer

c# - 如何配置 Startup 类构造函数可用的 DI 服务

c# - 如何模块化此 C# 代码?

c# - 是否有执行 .SelectMany(x => x) 的 Linq 方法?

c# - 无法让 HTTP PUT 请求在 ASP.NET Core 中工作

c# - ASP.NET Core 中全局过滤器的顺序

c# - 如何填补列表中属性值的空白?

c#:带有多个条件的字典的 Linq

c# - 将 LINQPAD 连接到 Azure 存储

c# - 如何根据 ASP.NET Core MVC 中用户表的字段添加声明?