当我们在实体框架核心中拥有主键时,是否应该始终使用.Find()而不是.FirstOrDefault()?

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

microsoft文档示例中, .FirstOrDefaultAsync()用在DetailDelete GET中; .FindAsync()中使用了DeleteConfirmed。 我想知道为什么吗?

zhw335152 回答:当我们在实体框架核心中拥有主键时,是否应该始终使用.Find()而不是.FirstOrDefault()?

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

///     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询问提供者IQueryable.GetProvider()的接口,然后调用IQueryProvider.Execute(Expression)以获取由Expression定义的数据。 这将始终访问数据库。

假设您的学校与学生在一起,这是一种简单的一对多关系。您还具有更改学生数据的过程。

Student ChangeAddress(dbContext,int studentId,Address address);
Student ChangeSchool(dbContext,int SchoolId);

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

您具有使用以下过程的以下代码:

void ChangeStudent(int studentId,Address address,int schoolId)
{
    using (var dbContext = new SchoolDbContext())
    {
        ChangeAddress(dbContext,studentId,address);
        ChangeSchool(dbContext,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
,

我认为这是因为进行“删除”时,您不知道该项目是否存在,因此需要默认设置,以防找不到。

在执行DeleteConfirmed时,您知道带有id的项目存在并且可以使用Find

本文链接:https://www.f2er.com/3135040.html

大家都在问