如何在实体框架中对子表应用Where条件



我有以下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上应用条件;条件是CCD_ 2和CCD_。我做不到。

我不想用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所基于的关系演算保持一致,这也意味着您可以立即检查JOIN是否正确,因为您总是只使用主键和外键列(它们可能已经被索引了…对吧?(。

因此,您的查询变成:

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到实体:

还有:

  • 您不需要.AsQueryable()调用:从DbContextDbSet<T>创建的所有非物化查询都将是IQueryable<T>
  • 由于您具有导航属性,因此不需要手动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

我不能直接添加Include( b => b.BarStatus ),因为BarStatusBarCode没有直接关系,它与BarDetail链接。因此,首先我们进入BarDetail,然后使用barstatus1 进入BarStatus

您仍然可以手动执行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);

最新更新