我有以下查询,我正在寻找的是优化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();
答案 0 :(得分:1)
嗯,也许有更好的解决方案,但是您可以使用扩展名FirstOrDefault
代替使用Any
的条件:
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();
答案 1 :(得分:1)
通过将查询语法与let
clause配合使用,可以防止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
子句代替重复的子查询。