我想在LINQ中翻译这个查询...如果我们在纯SQL中进行构建很容易,但是在动态创建的LINQ查询中(根据用户输入构建搜索查询)这是一个全新的故事。
SELECT * FROM MyTable
WHERE 1=1
AND Column2 IN (1,2,3)
AND ( Column1 LIKE '%a%' OR Column1 LIKE '%b%' )
现在尝试构建它,我们尝试了这种方式:
if(myOjb.Column2Collection != null)
query = query.where(f => f.Column2.Contains(myOjb.Column2Collection));
if(myObj.Column1Collection != null)
{
// tough part here ?
//query = query.Where(); ...
}
那么通常情况下最好的方法是什么?
请注意,我知道SqlMethod.Like,因为我无法想办法在这里实现它...
答案 0 :(得分:1)
要获得Like ..或Like ..等,我认为你必须编写自己的扩展来为你构建表达式树。我想在不久前做到这一点,最后在StackOverflow上找到另一篇文章:Linq to Sql any keyword search query
从那里开始,我想你会写下这个:
string[] terms = new string[] {"a", "b"}
query = query.LikeAny(table => table.Column1, terms)
顺便说一句,您也可以通过更改
来更改链接页面上的代码以进行AND而不是ORvar body = conditions.Aggregate((acc, c) => Expression.Or(acc, c));
到
var body = conditions.Aggregate((acc, c) => Expression.And(acc, c));
这是我当时想要的,称之为LikeAll
答案 1 :(得分:0)
尝试这样的事情:
var colums2 = { 1, 2, 3 };
var result = (from o in myOjb
where columns2.Any(co2 => co2 == o.Column2)
&& Column1.Contains(column2valueA)
|| Column1.Contains(column2valueB)
select o);
希望可以提供帮助
答案 2 :(得分:0)
var sc = StringComparison.OrdinalIgnoreCase;
var col2Values = new int[] { 1, 2, 3 };
var query = from item in myObj
where col2Values.Contains(item.Column2)
&& (item.Column1.IndexOf("a", sc) >= 0
|| item.Column1.IndexOf("b", sc) >= 0)
select item;
我还没有测试过,但它构建得很好。如果上述原因失败,则为原始版本:
var col2Values = new int[] { 1, 2, 3 };
var query = from item in myObj
let col1 = item.Column1.ToLower()
where col2Values.Contains(item.Column2)
&& (col1.Contains("a") || col1.Contains("b"))
select item;
我实际上更喜欢第二个版本,即使由于ToLower()
而稍微较慢。在我看来,它更容易阅读。 YMMV。
答案 3 :(得分:0)
from o in myObj
where
new[] { 1, 2, 3 }.Contains(o.Column2) &&
new[] { "a", "b" }.Any(s => o.Column1.IndexOf(s, StringComparison.Ordinal) != -1)
select o;
如果您关心查找性能,请使用new Hashset<T>
。数组只带来O(n)。
Ordinal
表示unicode比较每字节字节,没有特定于文化的问题,最快。
OrdinalIgnoreCase
表示相同但区分大小写
答案 4 :(得分:0)
尝试this。