Entity framework core 更新已跟踪的实体

Entity framework core 更新已跟踪的实体,entity-framework-core,Entity Framework Core,我想更新itemsToUpdate集合。 此集合已在查询中使用,因此已在上下文本地属性中跟踪生成的实体 从itemsToUpdate集合重写context.items.Local属性的最有效方法是什么 private async Task<IEnumerable<item>> GetitemsAsync(IEnumerable<item> itemIds) { return await context.i

我想更新itemsToUpdate集合。 此集合已在查询中使用,因此已在上下文本地属性中跟踪生成的实体

从itemsToUpdate集合重写context.items.Local属性的最有效方法是什么

private async Task<IEnumerable<item>> GetitemsAsync(IEnumerable<item> itemIds)
            {
                return await context.items.Where(t => itemIds.Select(x => x.Id).Contains(t.Id)).ToListAsync();
            }

public async Task Update(...)
{
            // Update
            var queryUpdateitems = await GetitemsAsync(itemsToUpdate);

            bool canUpdate = queryUpdateitems.All(t => t.UserId == userId);
            if (!canUpdate)
            {
                throw new NotAuthorizedException();
            }
            else
            {
               // update here the itemsToUpdate collection
            }

            context.SaveChangesAsync();
}
专用异步任务GetitemsAsync(IEnumerable ItemId)
{
返回wait context.items.Where(t=>itemIds.Select(x=>x.Id).Contains(t.Id)).toListSync();
}
公共异步任务更新(…)
{
//更新
var queryUpdateitems=await GetitemsAsync(itemsToUpdate);
bool canUpdate=queryUpdateitems.All(t=>t.UserId==UserId);
如果(!canUpdate)
{
抛出新的NotAuthorizedException();
}
其他的
{
//在此更新itemsToUpdate集合
}
context.saveChangesSync();
}

在您的情况下,您知道必须更新所有这些项目,您只需要确保当前用户可以更新所有项目(通过比较
Item.UserId
)。您可以查询数据库以给出检查结果,而不是从数据库中获取所有现有项来进行检查,然后只要在检查为true时向数据库发送更新即可

var itemIds = itemsToUpdate.Select(x => x.Id).ToList();
var canUpdate = await db.Blogs.Where(b => itemIds.Contains(b.Id)).AllAsync(t => t.UserId == userId);
if (canUpdate)
{
    db.UpdateRange(itemsToUpdate);
}
else
{
    throw new NotSupportedException();
}

await db.SaveChangesAsync();
在这里,您必须首先创建ItemID列表,因为EF不能在查询中内联项目列表,否则将在客户端上进行计算。这意味着EF正在获取整个表。您的
GetitemsAsync
方法也是如此。它还查询整个表。考虑在该方法中本地创建ITEMID。


一旦您在方法中传入
列表
,EF将很乐意将其内联到查询中,对于
canUpdate
的查询,它将向数据库发送单个查询,并从数据库中获取true/false。然后您可以直接使用
UpdateRange
,因为没有更多的跟踪记录。因为它不能从数据库中获取所有项目,所以速度也会更快。

你的意思是我不能:db.Blogs.Where(b=>itemToUpdate.Select(x=>x.Id).Contains(b.Id).AllAsync(等等)?您可以这样编写linq,但由于itemsToUpdate是
列表
,无法直接在SQL中表示,它将导致客户端求值。因此EF将从数据库中获取所有记录,并在内存中应用筛选器。我没有在数据库上执行AllAsync的原因是因为我仍然希望处理Id
s,其中do不存在,并在查询结果为空时引发BadDataException。不过,我想现在我不关心不存在Id
s或Id具有错误的用户Id。在这两种情况下,我都会让用户知道他没有此资源的权限。感谢您的代码工作:-)