Dot-Net
EF Core linq 和條件包含然後包含問題
嘗試獲取具有多個級別的對象時,我在獲取結果時遇到問題。這就是我要大致做的事情:
_context.Investors.Where(s => s.Id == userId) .Include(c => c.Coins) //only want this if some kind of flag is given by the user. .ThenInclude(ct => ct.CoinType) .Include(c => c.Bricks) //only want this if some kind of flag is given by the user.本質上,我得到了很多標誌,表明我是否應該包含對象的某些部分。我幾乎可以工作了。像這樣:
_context.Investors.Where(s => s.Id == userId) .Select(i => new { i, Bricks = (details & GapiInvestorFlags.Bricks) != GapiInvestorFlags.Bricks ? null : i.Bricks, Offers = (details & GapiInvestorFlags.Offers) != GapiInvestorFlags.Offers ? null : i.Offers, Coins = (details & GapiInvestorFlags.Coins) != GapiInvestorFlags.Coins ? null : i.Coins, CoinTransactions = (details & GapiInvestorFlags.CoinTransactions) != GapiInvestorFlags.CoinTransactions ? null : i.CoinTransactions, OfferTransactions = (details & GapiInvestorFlags.OfferTransactions) != GapiInvestorFlags.OfferTransactions ? null : i.OfferTransactions, BuyTransactions = (details & GapiInvestorFlags.BuyTransactions) != GapiInvestorFlags.BuyTransactions ? null : i.BuyTransactions, SellTransactions = (details & GapiInvestorFlags.SellTransactions) != GapiInvestorFlags.SellTransactions ? null : i.SellTransactions }).AsEnumerable() .Select(e => e.i).FirstOrDefault();除了硬幣部分也有一個硬幣類型,所以我也需要包含它。但是當我添加我的程式碼時,整個部分停止工作。
這是我嘗試過的:
_context.Investors.Where(s => s.Id == userId) .Include(c => c.Coins) .ThenInclude(ct => ct.CoinType) .Select(i => new { i, Bricks = (details & GapiInvestorFlags.Bricks) != GapiInvestorFlags.Bricks ? null : i.Bricks, Offers = (details & GapiInvestorFlags.Offers) != GapiInvestorFlags.Offers ? null : i.Offers, Coins = (details & GapiInvestorFlags.Coins) != GapiInvestorFlags.Coins ? null : i.Coins.Select(c => new { c, c.CoinType }).ToList(), CoinTransactions = (details & GapiInvestorFlags.CoinTransactions) != GapiInvestorFlags.CoinTransactions ? null : i.CoinTransactions, OfferTransactions = (details & GapiInvestorFlags.OfferTransactions) != GapiInvestorFlags.OfferTransactions ? null : i.OfferTransactions, BuyTransactions = (details & GapiInvestorFlags.BuyTransactions) != GapiInvestorFlags.BuyTransactions ? null : i.BuyTransactions, SellTransactions = (details & GapiInvestorFlags.SellTransactions) != GapiInvestorFlags.SellTransactions ? null : i.SellTransactions }).AsEnumerable() .Select(e => e.i).FirstOrDefault();我真的不知道為什麼它不起作用。
基本上當我改變時:
i.Coins到
i.Coins.Select(c => new { c, c.CoinType }).ToList()它停止工作。
您使用的技術並不是真正的顯式載入 (
Include/ThenInclude),而是基於投影和 EF Core 導航屬性修復的技巧,所以我不能說它為什麼停止工作。EF Core 仍以不同方式處理投影和包含,因此它可能是目前處理中的缺陷。在根查詢級別實現條件包含相對容易。請注意,該
Include方法從 (is defined for) 開始IQueryable<TEntity>,返回IIncludableQueryable<TEntity, TPreviousProperty>>的也是IQueryable<TEntity>. 這意味著您可以保留IQueryable<T>查詢變數並應用類似於鍊式Where運算符的條件轉換。為了使這更容易,您可以創建一個自定義幫助擴展方法,如下所示:
public static IQueryable<T> If<T>( this IQueryable<T> source, bool condition, Func<IQueryable<T>, IQueryable<T>> transform ) { return condition? transform(source) : source; }並像這樣使用它:
_context.Investors.Where(s => s.Id == userId) .If(flagCoins, q => q.Include(e => e.Coins) .ThenInclude(e => e.CoinType)) .If(flagBricks, q => q.Include(e => e.Bricks))如果嵌套級別 (
ThenInclude) 需要類似的東西,則添加以下 2 個擴展方法:public static IQueryable<T> If<T, P>( this IIncludableQueryable<T, P> source, bool condition, Func<IIncludableQueryable<T, P>, IQueryable<T>> transform ) where T : class { return condition ? transform(source) : source; } public static IQueryable<T> If<T, P>( this IIncludableQueryable<T, IEnumerable<P>> source, bool condition, Func<IIncludableQueryable<T, IEnumerable<P>>, IQueryable<T>> transform ) where T : class { return condition ? transform(source) : source; }這將允許您使用這樣的東西:
_context.Investors.Where(s => s.Id == userId) .If(flagCoins, q => q.Include(e => e.Coins) .If(flagCoinType, q2 => q2.ThenInclude(e => e.CoinType))) .If(flagBricks, q => q.Include(e => e.Bricks))