我有一个使用linq从Words
表搜索的函数。我想.split(' ')
输入单词并搜索每个单词。但我希望or
在我的条件之间而不是and
。请参阅生成的SQL代码。
public static List<Word> GetWords(string word_Fa, string word_En)
{
var db = Global.GetEntitiy();
var query = from item in db.Words
select item;
foreach (var item in word_Fa.Split(' '))
{
query = query.Where(a => a.Word_Fa.Contains(item));
}
foreach (var item in word_En.Split(' '))
{
query = query.Where(a => a.Word_En.Contains(item));
}
return query.ToList();
}
生成的SQL代码:
SELECT [t0].[ID], [t0].[UserID], [t0].[Word_En], [t0].[Word_Fa], [t0].[UpVotes], [t0].[DownVotes], [t0].[DateTime], [t0].[Status]
FROM [Words] AS [t0]
WHERE ([t0].[Word_En] LIKE @p0) AND ([t0].[Word_En] LIKE @p1) AND ([t0].[Word_Fa] LIKE @p2) AND ([t0].[Word_Fa] LIKE @p3)
答案 0 :(得分:2)
您可以考虑使用来自Here的谓词构建器,正如@Hadi Hassan在评论中所说的那样。 通过使用它,您的代码将是这样的:
var predicate = PredicateBuilder.False<Words>();
var query = from item in Words
select item;
var FaWords = "A B C".Split(' ');
var EnWords = "D E F".Split(' ');
foreach (string item in FaWords)
{
predicate = predicate.Or(p => p.Word_Fa.Contains(item));
}
foreach (string item in EnWords)
{
predicate = predicate.Or(p => p.Word_En.Contains(item));
}
return query.Where(predicate).toList();
并且sql查询将是:
SELECT [t0].[ID], [t0].[UserID], [t0].[Word_En], [t0].[Word_Fa], [t0].[UpVotes], [t0].
[DownVotes], [t0].[DateTime], [t0].[Status]
FROM [Words] AS [t0]
WHERE ([t0].[Word_Fa] LIKE @p0) OR ([t0].[Word_Fa] LIKE @p1) OR ([t0].[Word_Fa] LIKE @p2) OR ([t0].[Word_En] LIKE @p3) OR ([t0].[Word_En] LIKE @p4) OR ([t0].[Word_En] LIKE @p5)
顺便说一下,如果你遇到这个错误:LINQ to Entities不支持LINQ表达式节点类型'Invoke'。
您应该将LinqKit nuget包添加到项目中,并将返回行更改为:
return query.AsExpandable().Where(predicate).toList();
祝你好运
答案 1 :(得分:2)
不使用LinqKit的解决方案:
扩展类与PredicateBuilder非常相似,但它可以与linq一起使用实体,而linq可以直接使用sql:
public static class PredicateHelper
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
if (expr1 == null)
{
throw new ArgumentNullException("expr1");
}
if (expr2 == null)
{
throw new ArgumentNullException("expr2");
}
var visitor = new ParameterUpdateVisitor(expr2.Parameters.First(), expr1.Parameters.First());
expr2 = visitor.Visit(expr2) as Expression<Func<T, bool>>;
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters);
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
if (expr1==null)
{
throw new ArgumentNullException("expr1");
}
if (expr2 == null)
{
throw new ArgumentNullException("expr2");
}
var visitor = new ParameterUpdateVisitor(expr2.Parameters.First(), expr1.Parameters.First());
expr2 = visitor.Visit(expr2) as Expression<Func<T, bool>>;
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
}
class ParameterUpdateVisitor : ExpressionVisitor
{
private readonly ParameterExpression _oldParameter;
private readonly ParameterExpression _newParameter;
public ParameterUpdateVisitor(ParameterExpression oldParameter, ParameterExpression newParameter)
{
_oldParameter = oldParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (ReferenceEquals(node, _oldParameter))
return _newParameter;
return base.VisitParameter(node);
}
}
}
使用绝对等于PredicateBuilder:
var predicate = PredicateBuilder.False<Words>();
var query = from item in Words
select item;
var FaWords = "A B C".Split(' ');
var EnWords = "D E F".Split(' ');
foreach (string item in FaWords)
{
var item1 = item;
predicate = predicate.Or(p => p.Word_Fa.Contains(item1));
}
foreach (string item in EnWords)
{
var item1 = item;
predicate = predicate.Or(p => p.Word_En.Contains(item1));
}
return query.Where(predicate).toList();
答案 2 :(得分:0)
除非我遗漏了什么,否则我觉得这对你有用:
public static List<Word> GetWords(string word_Fa, string word_En)
{
var db = Global.GetEntitiy();
return db.Words
.Where(w => w.Word_Fa.Intersect(word_Fa.Split(' ')).Any() ||
w.Word_En.Intersect(word_En.Split(' ')).Any())
.ToList();
}
答案 3 :(得分:-1)
您想要word_Fa
中query
中word_Fa.Split(' ')
中的每个项目检查query
。因此,将它们加入到该字符串中,它将为word_Fa.Split(' ')
中的所有项目提供var query1 = (from q in query
join item in word_Fa.Split(' ') on q.Word_Fa equals item
select q).ToList();
var query2 = (from q in query
join item in word_En.Split(' ') on q.Word_En equals item
select q).ToList();
return query1.Union(query2);
中的所有项目:
{{1}}