如何在 Entity Framework 中对 Children Table 应用 Where 条件
How to apply Where condition on Children Table in Entity Framework
我有以下 SQL 查询,由于某些限制,因为此查询中有更多条件,我必须将此查询转换为 LINQ。
SELECT
sh.BarCode
FROM
Bars AS sh
INNER JOIN BarDetail AS detail ON
detail.BarCode = sh.BarCode
AND
detail.IsActive = 1
INNER JOIN BarStatus AS st ON
st.BarCode = sh.BarCode
AND
st.IsActive = 1
到目前为止我已经在 LINQ 上完成了这个
var queryAble = _context.BarDetail
.Include(x => x.Bar)
.Include(x => x.Bar)
.ThenInclude(y => y.BarStatus)
.Where(x => x.IsActive == true)
.AsQueryable();
我也想在 barstatus
上应用条件;条件是 barstatus
和 IsActive == true
。我做不到。
我不想用 DbCommand
作为原始 SQL 来做,我想完全只使用 Linq-to-Entities 来做。
我怎么会这样,但它不起作用
var queryAble = _context.BarDetail
.Include(x => x.Bar)
.Include(x => x.Bar)
.ThenInclude(y => y.BarStatus)
.Where(x => x.IsActive == true && x.Bar.BarStatus[SOMETHING HERE])
.AsQueryable();
这是将您的 SQL 直接转换为 LINQ。请注意,Include
引入不是为了构建查询而是为了加载相关数据。
var query =
from bar in _context.Bar
from detail in bar.Details
where detail.IsActive && bar.IsActive && bar.BarStatus.IsActive
select bar.BarCode;
正如我在评论中所说,虽然您的原始 SQL 查询 有效 ,但 JOIN
子句最好仅使用 键(或元组)相等,而其他谓词应在WHERE
子句中。遵循该模式不会对您的运行时查询执行计划造成任何更改,但我觉得它与 SQL 所基于的 relational-calculus 保持一致 - 这也意味着您可以立即检查 JOIN
是否正确,因为您将始终使用 only primary-key 和 foreign-key 列(可能已经编入索引... 对吗?).
因此您的查询变为:
SELECT
b.BarCode
FROM
Bars AS b
INNER JOIN BarDetail AS d ON d.BarCode = b.BarCode
INNER JOIN BarStatus AS s ON s.BarCode = b.BarCode
WHERE
d.IsActive = 1
AND
s.IsActive = 1
...更容易翻译成Linq-to-Entities:
还有:
- 您不需要
.AsQueryable()
调用:从 DbContext
的 DbSet<T>
创建的所有 non-materialized 查询都已经 IQueryable<T>
。
- 因为你有 navigation-properties 你不需要做一个手册
Join
.
IQueryable<String> q = _context.BarCode
// .Include( b => b.BarDetail )
// .Include( b => b.BarStatus )
.Where( b =>
b.BarDetail.IsActive == true
&&
b.BarStatus.IsActive == true
)
.Select( b => b.BarCode );
List<String> list = await q.ToListAsync( cancellationToken ).ConfigureAwait(false);
更新:没有b.BarDetail.IsActive == true
I can not directly add Include( b => b.BarStatus )
because BarStatus
doesn't have direct relationship with BarCode
, its linked with BarDetail
. So first we go into BarDetail
and then after that we go in BarStatus
using BarDetail
你仍然可以做一个手册JOIN
:
IQueryable<String> q = _context.BarCode
// .Include( b => b.BarDetail )
// .Include( b => b.BarStatus )
.Join( _context.BarStatus, s => s.BarCode, b => b.BarCode, ( s, b )
=> new { BarStatus = s, BarCode = b, BarDetail = b.BarDetail } )
.Where( t =>
t.BarDetail.IsActive == true
&&
t.BarStatus.IsActive == true
)
.Select( b => b.BarCode );
List<String> list = await q.ToListAsync( cancellationToken ).ConfigureAwait(false);
我有以下 SQL 查询,由于某些限制,因为此查询中有更多条件,我必须将此查询转换为 LINQ。
SELECT
sh.BarCode
FROM
Bars AS sh
INNER JOIN BarDetail AS detail ON
detail.BarCode = sh.BarCode
AND
detail.IsActive = 1
INNER JOIN BarStatus AS st ON
st.BarCode = sh.BarCode
AND
st.IsActive = 1
到目前为止我已经在 LINQ 上完成了这个
var queryAble = _context.BarDetail
.Include(x => x.Bar)
.Include(x => x.Bar)
.ThenInclude(y => y.BarStatus)
.Where(x => x.IsActive == true)
.AsQueryable();
我也想在 barstatus
上应用条件;条件是 barstatus
和 IsActive == true
。我做不到。
我不想用 DbCommand
作为原始 SQL 来做,我想完全只使用 Linq-to-Entities 来做。
我怎么会这样,但它不起作用
var queryAble = _context.BarDetail
.Include(x => x.Bar)
.Include(x => x.Bar)
.ThenInclude(y => y.BarStatus)
.Where(x => x.IsActive == true && x.Bar.BarStatus[SOMETHING HERE])
.AsQueryable();
这是将您的 SQL 直接转换为 LINQ。请注意,Include
引入不是为了构建查询而是为了加载相关数据。
var query =
from bar in _context.Bar
from detail in bar.Details
where detail.IsActive && bar.IsActive && bar.BarStatus.IsActive
select bar.BarCode;
正如我在评论中所说,虽然您的原始 SQL 查询 有效 ,但 JOIN
子句最好仅使用 键(或元组)相等,而其他谓词应在WHERE
子句中。遵循该模式不会对您的运行时查询执行计划造成任何更改,但我觉得它与 SQL 所基于的 relational-calculus 保持一致 - 这也意味着您可以立即检查 JOIN
是否正确,因为您将始终使用 only primary-key 和 foreign-key 列(可能已经编入索引... 对吗?).
因此您的查询变为:
SELECT
b.BarCode
FROM
Bars AS b
INNER JOIN BarDetail AS d ON d.BarCode = b.BarCode
INNER JOIN BarStatus AS s ON s.BarCode = b.BarCode
WHERE
d.IsActive = 1
AND
s.IsActive = 1
...更容易翻译成Linq-to-Entities:
还有:
- 您不需要
.AsQueryable()
调用:从DbContext
的DbSet<T>
创建的所有 non-materialized 查询都已经IQueryable<T>
。 - 因为你有 navigation-properties 你不需要做一个手册
Join
.
IQueryable<String> q = _context.BarCode
// .Include( b => b.BarDetail )
// .Include( b => b.BarStatus )
.Where( b =>
b.BarDetail.IsActive == true
&&
b.BarStatus.IsActive == true
)
.Select( b => b.BarCode );
List<String> list = await q.ToListAsync( cancellationToken ).ConfigureAwait(false);
更新:没有b.BarDetail.IsActive == true
I can not directly add
Include( b => b.BarStatus )
becauseBarStatus
doesn't have direct relationship withBarCode
, its linked withBarDetail
. So first we go intoBarDetail
and then after that we go inBarStatus
usingBarDetail
你仍然可以做一个手册JOIN
:
IQueryable<String> q = _context.BarCode
// .Include( b => b.BarDetail )
// .Include( b => b.BarStatus )
.Join( _context.BarStatus, s => s.BarCode, b => b.BarCode, ( s, b )
=> new { BarStatus = s, BarCode = b, BarDetail = b.BarDetail } )
.Where( t =>
t.BarDetail.IsActive == true
&&
t.BarStatus.IsActive == true
)
.Select( b => b.BarCode );
List<String> list = await q.ToListAsync( cancellationToken ).ConfigureAwait(false);