[英]Linq Query Optimization in Entity Framework
我有以下查询,我正在寻找的是优化where
子句。 我不喜欢FirstOrDefault
的多种用法。 有没有可能用Join
或其他方法来实现它,这样我将只能访问一次FirstOrDefault
?
var promos = await this._context
.SinglePromotions
.Include(p => p.Rewards)
.Include(p => p.InAppProduct)
.Include(p => p.PlayerSinglePromotions)
.ThenInclude(sp => sp.Player)
.ThenInclude(pl => pl.Purchases)
.Where(p => p.MinimumPlayerLevel <= Player.Level &&
p.Placement == placement &&
p.IsActive &&
(p.PlayerSinglePromotions.All(sp => sp.PlayerID != Player.ID) ||
(p.PlayerSinglePromotions.FirstOrDefault(sp => sp.PlayerID == Player.ID).PurchaseAmount < p.PurchaseLimit)) &&
(p.PlayerSinglePromotions.All(sp => sp.PlayerID != Player.ID) || (p.PlayerSinglePromotions.FirstOrDefault(sp => sp.PlayerID == Player.ID).Player.Purchases.Count <= p.MaxInAppPurchasesByPlayer))
)
.ToListAsync();
好吧,也许有更好的解决方案,但是您可以使用Any
扩展方法替换使用FirstOrDefault
条件:
var promos = await this._context.SinglePromotions
.Include(p => p.Rewards)
.Include(p => p.InAppProduct)
.Include(p => p.PlayerSinglePromotions)
.ThenInclude(sp => sp.Player)
.ThenInclude(pl => pl.Purchases)
.Where(
p => p.MinimumPlayerLevel <= Player.Level &&
p.Placement == placement &&
p.IsActive &&
(p.PlayerSinglePromotions.All(sp => sp.PlayerID != Player.ID) ||
p.PlayerSinglePromotions.Any(sp => sp.PlayerID == Player.ID
&& (sp.Player.Purchases.Count <= p.MaxInAppPurchasesByPlayer || sp.PurchaseAmount < p.PurchaseLimit))))
.ToListAsync();
通过使用带有let
子句的查询语法,可以防止LINQ查询中长表达式的重复。 这就像声明包含表达式结果的变量一样。 在您的查询中,重复了两部分,可以在let
变量中捕获它们:
var promos = await (
from p in this._context.SinglePromotions
.Include(p => p.Rewards)
.Include(p => p.InAppProduct)
.Include(p => p.PlayerSinglePromotions)
.ThenInclude(sp => sp.Player)
.ThenInclude(pl => pl.Purchases)
let pspNotOfPlayer = p.PlayerSinglePromotions.All(sp => sp.PlayerID != Player.ID)
let firstPromotion = p.PlayerSinglePromotions.FirstOrDefault(sp => sp.PlayerID == Player.ID)
where
p.MinimumPlayerLevel <= Player.Level
&& p.Placement == placement
&& p.IsActive
&& pspNotOfPlayer || firstPromotion.PurchaseAmount < p.PurchaseLimit
&& pspNotOfPlayer || firstPromotion.Player.Purchases.Count <= p.MaxInAppPurchasesByPlayer
select p
)
.ToListAsync();
在许多情况下,这不仅可以提高代码的可读性,而且可以改善生成的SQL,因为可以用CROSS APPLY
子句代替重复的子查询。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.