我有一个LINQ结果集我试图以一种奇怪而奇特的方式过滤。
List<string> MyDomains = [Code to get list];
var x = (from a in dc.Activities
where a.Referrer != null
&& a.Referrer.Trim().Length > 0
&& !a.Referrer.Contains("localhost")
&& a.SearchResults.Count() == 0
orderby a.ID descending
select a)
.Take(20);
现在我已经解决了这个问题,让我更好地解释一下。 MyDomains是一个字符串列表;每个人都是我拥有的根域。
a.Referrer是一个字符串,包含从GET到我的某个网站的引荐来源。请注意,此字符串将包含子域,文件夹,文件和查询字符串。
我想通过位于MyDomains列表中的a.Referrer的根域过滤x。也就是说,我希望以这种方式返回所有不匹配的记录。结果集应该最终包含其Referler不是我的域之一的活动。
我一直在学习Lambda表达式,但到目前为止还没有能够设法实现这个目标,因为它实际上需要一个带有逻辑的where子句(可能是循环,子串等)。
目前我正在考虑将X转换为List,手动过滤它们,然后将列表绑定到目标控件而不是绑定X.我有一个扩展方法来获取Uri的根域,另一个确定是否它是我的域名,但不能将它们放在Lambda中,因为它们“没有支持的SQL转换”。
除了建筑上的分歧之外,我如何在LINQ查询中实现这一点?
答案 0 :(得分:1)
如果我理解正确,您希望获得按ID排序的前20个活动,其推荐人字段不包含MyDomains中的任何项目作为子字符串。
以下或类似的东西应该有效:
var theActivities = (from a in dc.Activities
where a.Referrer != null
&& a.Referrer.Trim().Length > 0
&& a.SearchResults.Count() == 0
select a);
foreach(var domain in MyDomains) {
theActivities = theActivities.Except(dc.Activities.Where(a => a.Referrer.Contains(domain)));
}
theActivities = theActivities.OrderBy(a => a.Id).Take(20);
//Now you can query theActivities
但是请注意,最终会得到一个相当长的SQL查询,因为将为MyDomains中的每个项添加一个WHERE子句。
更新:确实,这不起作用。由于查询表达式在实际查询时被计算,因此所有Except
子句对domain
变量使用相同的值(这是最后一个值集)。
我能想到的唯一解决方案是动态生成SQL命令来获取数据。我现在无法验证代码,但它大概是这样的:
var whereClauses=new List<string>();
for(int i=0; i<MyDomains.Length; i++) {
whereClauses.Add(string.Format("(Referrer like {{{0}}})", i));
}
var sqlFormattedDomains=MyDomains.Select(d => string.Format("%{0}%", d)).ToArray();
var sqlCommand=string.Format(
"select top 20 * from Activities where (not Referrer is null) and (not ({0})) order by Id",
sqlFormattedDomains.Join(" or "));
var x=dc.ExecuteQuery<Activities>(sqlCommand, sqlFormattedDomains);
您必须扩展SearchResults.Count() == 0
条件的SQL命令,我想这与将join子句添加到另一个表有关。
答案 1 :(得分:0)
我认为添加
&& !MyDomains.Contains(a.Referrer)
应该做的伎俩