我在 for 循环中调用了下面的
ExecuteUpdate
,我想知道是否可以消除 For
循环并将 ExecuteUpdate
作为一次调用运行?
foreach (var registrant in yogabandEvent.Registrants)
{
result = await _dbContext.Users
.Where(p => p.Id == registrant.UserId)
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.Attended, registrant.RegistrantType == RegistrantType.Student ? p => p.Attended + 1 : p => p.Attended)
.SetProperty(p => p.Hosted, (registrant.RegistrantType == RegistrantType.Host || registrant.RegistrantType == RegistrantType.HostInstructor) ? p => p.Hosted + 1 : p => p.Hosted)
.SetProperty(p => p.Instructed, registrant.RegistrantType == RegistrantType.Instructor ? p => p.Instructed + 1 : p => p.Instructed)
);
}
ExecuteUpdate
生成一条发送到数据库的更新语句。因此,不可能使用复杂的本地数据,例如 yogabandEvent.Registrants
,这些数据应该在语句运行时读取,因此无法消除循环。
但是,在您的情况下,可以轻松地重组更新以创建一个完成这项工作的更新语句。由于您只更新
Users
,其中 yogabandEvent.Registrants
的类型为 Student
,因此您可以先收集这些 Id 并在更新语句中使用 Contains
:
var studentIds = yogabandEvent.Registrants
.Where(r => r.RegistrantType == RegistrantType.Student)
.Select(r => r.UserId)
.ToList();
result = await _dbContext.Users
.Where(p => studentIds.Contains(p.Id))
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.Attended, p => p.Attended + 1));
我关注了一个用户帖子,该帖子已被删除,但为我提供了我正在寻找的内容,所以我将发布我自己问题的解决方案。您可以在下面看到,现在我可以提供一个没有 for 循环的单个调用,该调用在每个
SetProperty
内都有可应用于 ID 列表的条件,从而消除任何 for 循环或执行多个 ExecuteUpdate
调用。
var studentIds = yogabandEvent.Registrants
.Where(x => x.RegistrantType == RegistrantType.Student)
.Select(x => x.UserId);
var hostId = 1;
var instructorId = 2
result = await _dbContext.Users
.Where(p => yogaClass.Registrants.Select(x => x.UserId).Contains(p.Id))
.ExecuteUpdateAsync(setters => setters
.SetProperty(p => p.Attended, p => p.Attended + (studentIds.Contains(p.Id) ? 1 : 0))
.SetProperty(p => p.Hosted, p => p.Hosted + (p.Id == hostId ? 1 : 0))
.SetProperty(p => p.Instructed, p => p.Instructed + (p.Id == instructorId ? 1 : 0))
);