EF Core linq 和条件包含然后包含问题 [英] EF Core linq and conditional include and theninclude problem
问题描述
在尝试获取具有多个级别的对象时,我在获取结果时遇到问题.这就是我大致要做的:
I am having a problem with getting a result when trying to get objects with multiple levels. This is what I am trying to do roughly:
_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.
从本质上讲,我收到了很多标志,表明我是否应该包含对象的一部分.我几乎可以工作了.像这样:
Essentially I am getting a lot of flags indicating if I should include parts of the object. I got it almost to work. Like this:
_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();
除了 Coins 部分也有一个硬币类型,所以我也需要包括它.但是当我添加我的代码时,整个部分停止工作.
This works except that the Coins section also has a cointype in it so I need to include it too. But when I add my code, the whole section stops working.
这是我试过的:
_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 really can't tell why it does not work.
基本上当我改变时:
i.Coins
到
i.Coins.Select(c => new { c, c.CoinType }).ToList()
它停止工作.
推荐答案
您使用的技术并不是真正的显式加载 (Include
/ThenInclude
),而是基于技巧的关于投影和 EF Core 导航属性修复,所以我不能说它为什么停止工作.EF Core 仍然以不同方式处理投影和包含,因此它可能是当前处理中的缺陷.
The technique you are using is not really explicit loading (Include
/ ThenInclude
), but trick based on projection and EF Core navigation property fix-up, so I can't say why it stops working. EF Core still processes projections and includes differently, so it might be a defect in the current processing.
在根查询级别实现条件包含相对容易.请注意,Include
方法从(为)IQueryable
开始,并且返回的 IIncludableQueryable
也是IQueryable
.这意味着您可以保留 IQueryable
查询变量并应用类似于链式 Where
运算符的条件转换.
Implementing conditional include at the root query level is relatively easy. Note that the Include
method starts from (is defined for) IQueryable<TEntity>
and the returned IIncludableQueryable<TEntity, TPreviousProperty>>
is also IQueryable<TEntity>
. Which means you can keep IQueryable<T>
query variable and apply conditional transformations similar to chained Where
operators.
为了更容易,您可以创建一个自定义的辅助扩展方法,如下所示:
To make that easier, you could create a custom helper extension method like this:
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 个扩展方法:
If you need something similar for the nested levels (ThenInclude
), then add the following 2 extension methods:
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;
}
这将允许你使用这样的东西:
which will allow you to use something like this:
_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))
这篇关于EF Core linq 和条件包含然后包含问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!