如何从 linq 的查询结果中排除?
How to exclude from query's result in linq?
在第一张图片中,我有第一个查询的结果,突出显示的部分表示将通过在第二个查询上应用过滤器来排除的行,在第二个图片中,我有查询的结果 select * from exlusion_table
我必须更改第一个查询以使其排除从第二个查询中检索到的项目
第一个查询:
var u = from a in cx.VW_LIST
where (a.PRJ == codPrj) && (a.DATE > date_ || a.DATE == null || date_ == null)
&& (x.Contains(a.CODE) || x.Count() == 0)
select a)
第二个查询:
var y = from esc in cx.EXCLUSION select esc
应修改第一个查询以排除所有具有值 fcode = 第二个查询的 fcode(在第二个查询的 fscode = null 的情况下)或那个(fcode = fcode of第二个查询 && fscode = 第二个查询的 fscode )
您可以使用 Any()。即:
var u = from a in cx.VW_LIST
where (a.PRJ == codPrj)
&& (a.DATE > date_ || a.DATE == null || date_ == null)
&& (x.Contains(a.CODE) || x.Count() == 0)
&& (!cx.EXCLUSION.Any( y => x.fscode == y.fscode && x.fcode == y.fcode ))
select a)
有两种方法,一种是使用!
和ANY()
过滤掉在另一个列表中找到的记录,这将编译成WHERE NOT EXISTS(_exclusion_)
过滤表达式
var excluded = cx.EXCLUSION.AsQueryable();
var query = from vw in cx.VW_LIST
where vw.PRJ == codPrj
where vw.DATE == null || date_ == null || vw.DATE > date_
where !x.Any() || x.Contains(vw.CODE)
where !excluded.Any(esc => vw.fcode == esc.fcode
&& (esc.fscode == null || vw.fscode == esc.fscode))
select vw;
var results = query.ToList();
棘手的元素是排除的 table 中 fscode
的 null
,它需要作为通配符匹配,或者否定 fscode
比较。
没有必要将 excluded
查询拆分成它自己的查询,我们可以直接引用 cx.EXCLUSION
table,它会产生完全相同的效果,这向您展示了一种用于构建 LINQ 查询的封装技术,您可以轻松地增加排除查找的复杂性,而不会造成整个查询的混乱。
您可能还发现需要有条件地构建查询,这就是 Fluent syntax 提供更模块化方法的地方:
bool filterExcludedRecords = true;
...
var excluded = cx.EXCLUSION.AsQueryable();
var query = cx.VW_LIST.Where(vw => vw.PRJ == codPrj)
.Where(vw => vw.DATE == null || date_ == null || vw.DATE > date_)
.Where(vw => !x.Any() || x.Contains(vw.CODE));
if(filterExcludedRecords)
query = query.Where(vw => !excluded.Any(esc => vw.fcode == esc.fcode
&& (esc.fscode == null || vw.fscode == esc.fscode)));
var results = query.ToList();
外连接
另一种方法是在未找到排除匹配项的地方使用 LFET OUTER JOIN
:
var excluded = cx.EXCLUSION.AsQueryable();
var query = from vw in cx.VW_LIST
where vw.PRJ == codPrj
where vw.DATE == null || date_ == null || vw.DATE > date_
where !x.Any() || x.Contains(vw.CODE)
from esc in excluded.Where(e => vw.fcode == e.fcode
&& (e.fscode == null || vw.fscode == e.fscode))
.DefaultIfEmpty()
where esc.fscode == null
select vw;
var results = query.ToList();
WHERE NOT EXISTS
通常在性能方面更胜一筹,OUTER JOIN
可能在 un-optimised table 或排除列表中的行数时提供更好的响应非常小,主要table中的行数非常大。
为了完整起见,我包含了这个查询选项,众所周知,您可以通过向查询添加新的 from
子句来创建简单的外部联接。
在第一张图片中,我有第一个查询的结果,突出显示的部分表示将通过在第二个查询上应用过滤器来排除的行,在第二个图片中,我有查询的结果 select * from exlusion_table
我必须更改第一个查询以使其排除从第二个查询中检索到的项目
第一个查询:
var u = from a in cx.VW_LIST
where (a.PRJ == codPrj) && (a.DATE > date_ || a.DATE == null || date_ == null)
&& (x.Contains(a.CODE) || x.Count() == 0)
select a)
第二个查询:
var y = from esc in cx.EXCLUSION select esc
应修改第一个查询以排除所有具有值 fcode = 第二个查询的 fcode(在第二个查询的 fscode = null 的情况下)或那个(fcode = fcode of第二个查询 && fscode = 第二个查询的 fscode )
您可以使用 Any()。即:
var u = from a in cx.VW_LIST
where (a.PRJ == codPrj)
&& (a.DATE > date_ || a.DATE == null || date_ == null)
&& (x.Contains(a.CODE) || x.Count() == 0)
&& (!cx.EXCLUSION.Any( y => x.fscode == y.fscode && x.fcode == y.fcode ))
select a)
有两种方法,一种是使用!
和ANY()
过滤掉在另一个列表中找到的记录,这将编译成WHERE NOT EXISTS(_exclusion_)
过滤表达式
var excluded = cx.EXCLUSION.AsQueryable();
var query = from vw in cx.VW_LIST
where vw.PRJ == codPrj
where vw.DATE == null || date_ == null || vw.DATE > date_
where !x.Any() || x.Contains(vw.CODE)
where !excluded.Any(esc => vw.fcode == esc.fcode
&& (esc.fscode == null || vw.fscode == esc.fscode))
select vw;
var results = query.ToList();
棘手的元素是排除的 table 中 fscode
的 null
,它需要作为通配符匹配,或者否定 fscode
比较。
没有必要将 excluded
查询拆分成它自己的查询,我们可以直接引用 cx.EXCLUSION
table,它会产生完全相同的效果,这向您展示了一种用于构建 LINQ 查询的封装技术,您可以轻松地增加排除查找的复杂性,而不会造成整个查询的混乱。
您可能还发现需要有条件地构建查询,这就是 Fluent syntax 提供更模块化方法的地方:
bool filterExcludedRecords = true;
...
var excluded = cx.EXCLUSION.AsQueryable();
var query = cx.VW_LIST.Where(vw => vw.PRJ == codPrj)
.Where(vw => vw.DATE == null || date_ == null || vw.DATE > date_)
.Where(vw => !x.Any() || x.Contains(vw.CODE));
if(filterExcludedRecords)
query = query.Where(vw => !excluded.Any(esc => vw.fcode == esc.fcode
&& (esc.fscode == null || vw.fscode == esc.fscode)));
var results = query.ToList();
外连接
另一种方法是在未找到排除匹配项的地方使用 LFET OUTER JOIN
:
var excluded = cx.EXCLUSION.AsQueryable();
var query = from vw in cx.VW_LIST
where vw.PRJ == codPrj
where vw.DATE == null || date_ == null || vw.DATE > date_
where !x.Any() || x.Contains(vw.CODE)
from esc in excluded.Where(e => vw.fcode == e.fcode
&& (e.fscode == null || vw.fscode == e.fscode))
.DefaultIfEmpty()
where esc.fscode == null
select vw;
var results = query.ToList();
WHERE NOT EXISTS
通常在性能方面更胜一筹,OUTER JOIN
可能在 un-optimised table 或排除列表中的行数时提供更好的响应非常小,主要table中的行数非常大。
为了完整起见,我包含了这个查询选项,众所周知,您可以通过向查询添加新的 from
子句来创建简单的外部联接。