我使用.NET Core 3.1和EF Core 3.1。我编写了一个方法,通过SQL Server数据库的Id
从中获取一行。
我的问题是,当我第一次提取数据时,它是可以的,但当我再次提取相同的数据时,第二次,数据没有正确提取,并返回a
变量数据,而不是数据库行(请参阅我代码中的注释(。
public async Task<AcademyStudent> GetItemAsync(Guid id)
{
var a = await _context.AcademiesStudents
.SingleOrDefaultAsync(x => x.Id == id);
// the value of property a.Mobile is "09123456789"
// change Mobile property with other data
a.Mobile = "0000";
// fetch again data from db with same query
var b = await _context.AcademiesStudents
.SingleOrDefaultAsync(x => x.Id == id);
// but the value of b.Mobile is not "09123456789" but also is "0000". why!??? :(
return b;
}
我的问题在哪里?如何解决?
这是因为实体框架跟踪实体及其更改。因此,一旦您将某个内容加载到上下文中,它就会返回该内容。
您需要在查询上使用.AsNoTracking()
await _context.AcademiesStudents
.AsQueryable()
.AsNoTracking()
.SingleOrDefaultAsync(x => x.Id == id);
a和b引用相同的数据对象。添加AsNoTracking()
efcore以防止跟踪状态更改。
无论如何,我都不建议打DB两次。如果这不仅仅是为了测试目的,我认为您还需要考虑您的实现逻辑。
首先:
// change Mobile property with other data
a.Mobile = "0000";
它自己什么都不做。您必须通过调用上下文的write或update函数将更改写入数据库。
第二:
var b = await _context.AcademiesStudents
.SingleOrDefaultAsync(x => x.Id == id);
做与完全相同的事情
var a = await _context.AcademiesStudents
.SingleOrDefaultAsync(x => x.Id == id);
因为lambda表达式的意思是:;使用Id查找具有该Id的对象,并将其放入a中。如果你想查询不同的对象,你必须查询不同的Id。
HTH-