gpt4 book ai didi

asp.net-core - 如何使用 'AsNoTracking' 方法结合显式加载相关实体在 EF Core 中加载实体

转载 作者:行者123 更新时间:2023-12-04 13:36:51 26 4
gpt4 key购买 nike

我目前正在使用这种方法来加载实体及其相关实体 AsNoTracking :

await DbContext.Clients
.Include(x => x.AllowedGrantTypes)
.Include(x => x.RedirectUris)
.Include(x => x.PostLogoutRedirectUris)
.Include(x => x.AllowedScopes)
.Include(x => x.ClientSecrets)
.Include(x => x.Claims)
.Include(x => x.IdentityProviderRestrictions)
.Include(x => x.AllowedCorsOrigins)
.Include(x => x.Properties)
.Where(x => x.Id == clientId)
.AsNoTracking()
.SingleOrDefaultAsync();

Github上的代码详细信息: link

这有效,但在迁移到 EF Core 3.0 后,此查询非常慢。

我发现可以通过像这样明确加载相关实体来解决这个性能问题:

IQueryable<Entities.Client> baseQuery = Context.Clients
.Where(x => x.Id == clientId)
.Take(1);

var client = await baseQuery.FirstOrDefaultAsync();
if (client == null) return null;

await baseQuery.Include(x => x.AllowedCorsOrigins).SelectMany(c => c.AllowedCorsOrigins).LoadAsync();
await baseQuery.Include(x => x.AllowedGrantTypes).SelectMany(c => c.AllowedGrantTypes).LoadAsync();
await baseQuery.Include(x => x.AllowedScopes).SelectMany(c => c.AllowedScopes).LoadAsync();
await baseQuery.Include(x => x.Claims).SelectMany(c => c.Claims).LoadAsync();
await baseQuery.Include(x => x.ClientSecrets).SelectMany(c => c.ClientSecrets).LoadAsync();
await baseQuery.Include(x => x.IdentityProviderRestrictions).SelectMany(c => c.IdentityProviderRestrictions).LoadAsync();
await baseQuery.Include(x => x.PostLogoutRedirectUris).SelectMany(c => c.PostLogoutRedirectUris).LoadAsync();
await baseQuery.Include(x => x.Properties).SelectMany(c => c.Properties).LoadAsync();
await baseQuery.Include(x => x.RedirectUris).SelectMany(c => c.RedirectUris).LoadAsync();


Github上的代码详细信息: link

不幸的是,我尝试用 AsNoTracking 重写这个示例。方法,但它不起作用 - 未加载相关实体。

如何使用 AsNoTracking 方法通过更快的性能重写我的原始查询?

我不需要为我的用例跟踪客户端实体。

最佳答案

正如 EF Core 文档所说,v3 现在生成连接,并且此查询是笛卡尔爆炸问题的受害者 https://docs.microsoft.com/en-us/ef/core/querying/related-data

文档还说,在以前的版本中,EF 为每个包含生成单独的查询。所以在我看来很好的解决方案是

var baseEntity = await DbContext.Clients.AsNoTracking().SingleOrDefaultAsync(x => x.Id == clientId);
baseEntity.AllowedGrantTypes = await DbContext.ClientCorsOrigins.AsNoTracking().Where(x => x.ClientId == clientID).ToListAsync();
baseEntity.RedirectUris = await DbContext.ClientRedirectUris.AsNoTracking().Where(x => x.ClientId == clientID).ToListAsync();
...
...

依此类推,直到您获得所需的所有相关资源。它将模仿以前的行为。
如果您确实需要使用导航属性,则不能使用 .AsNoTracking()很遗憾。如果我的想法看起来太天真 - 我能想到的唯一其他方法是在使用导航属性后将实体与跟踪上下文分离。

因此,从第二个链接实现代码后,您需要遍历对象中的实体并将它们标记为分离 DbContext.Entry(entity).State = EntityState.Detached;

关于asp.net-core - 如何使用 'AsNoTracking' 方法结合显式加载相关实体在 EF Core 中加载实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61316867/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com