我想在投影中使用Take(),但我不想产生N + 1查询,此外在投影中没有Take()时,我还面临性能问题。 我在EF6上使用了Take(),但在EF Core上却遇到了N + 1问题。
投影示例:
source.Select(post => new PostProject
{
PostDisableCoins = post.PostDisableCoins
.OrderBy(x=>x.CoinAmount)
.Take(3)
.ToList(),
WarStartTime = post.WarStartTime,
WarEndTime = post.WarEndTime,
WarWinner = post.WarWinner,
WarDeclarer = post.WarDeclarer
});
我想在没有N + 1的情况下使用Take(3),有什么建议吗?!?
答案 0 :(得分:1)
请注意有关EF core 2.1 new features:
的文档我们改进了查询翻译,以避免执行“ N + 1” SQL 在许多使用导航的常见方案中查询 投影中的属性导致根查询中的数据联接 来自相关子查询的数据。 优化需要 缓冲子查询的结果,我们要求您 修改查询以选择采用新行为 。
例如:
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount).ToList());
请注意,其中包含.ToList()
。
您需要相应地修改投影查询,以启用优化功能。
您的情况可能是:
source.Select(post => new PostProject
{
PostDisableCoins = post.PostDisableCoins
.Select(x => x.OrderBy(x=>x.CoinAmount))
.Select(x => x)
.Take(3)
.ToList(),
WarStartTime = post.WarStartTime,
WarEndTime = post.WarEndTime,
WarWinner = post.WarWinner,
WarDeclarer = post.WarDeclarer
});
答案 1 :(得分:1)
这是EF Core 2.1实施缺陷。以下是变通办法,但仅在确实存在性能问题时才使用它,因为它需要打破导航属性联接抽象并使用手动联接,我总是说这不应与EF(Core)一起使用。如果用于投影多个集合或作为更复杂的查询的一部分,也可能不起作用。
这要求使用横向联接将post.PostDisableCoins
集合导航属性SelectMany
的用法替换为OrderBy
并隐藏Take
/ var postDisableCoinsQuery = source.SelectMany(p =>
db.Set<PostDisableCoin>()
.Where(c => c.PostId == p.Id)
.OrderByDescending(c => c.CoinAmount)
.Take(3)
);
运算符(使用正确的类型和PK / FK名称):
GroupJoin
然后对它进行var query =
from p in source
join c in postDisableCoinsQuery on p.Id equals c.PostId into postDisableCoins
select new PostProject
{
PostDisableCoins = postDisableCoins.ToList(),
WarStartTime = p.WarStartTime,
WarEndTime = p.WarEndTime,
WarWinner = p.WarWinner,
WarDeclarer = post.WarDeclarer
};
:
import { NgModule } from '@angular/core';
import { Http, RequestOptions } from '@angular/http';
import { AuthHttp, AuthConfig } from 'angular2-jwt';
export function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({
tokenName: 'token',
tokenGetter: (() => sessionStorage.getItem('token')),
globalHeaders: [{'Content-Type':'application/json'}],
}), http, options);
}
@NgModule({
providers: [
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
}
]
})
export class AuthModule {}
执行后,上面的代码将通过单个SQL查询产生所需的结果。