问题描述
使用.Contains()/.StartsWith()/.EndsWith()时,生成的SQL如下所示:
When using .Contains()/.StartsWith()/.EndsWith() the generated SQL looks like this :
(( NVL(INSTR(x, y), 0) ) = 1)
有没有一种替代方法:
LIKE 'x%' or '%x%' or '%x'
因为在查询的执行计划中这两者之间存在巨大的成本差异(44 000 vs 30).
Because there is a huge cost difference between those two in the execution plan of the query (44 000 vs 30).
推荐答案
当我四处张望时,发现 LINQ中的LIKE运算符是a,其中有一些很好的示例说明了如何执行此操作.我已经测试了下面来自上面链接的那一个
When i look around abit i found LIKE operator in LINQ which were a which have a few good examples of how you could do this. I have tested the one below that was from the link above
这是 adobrzyc
public static class LinqEx
{
private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
public static Expression<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value)
{
var param = Expression.Parameter(typeof(TSource), "t");
var propertyInfo = GetPropertyInfo(property);
var member = Expression.Property(param, propertyInfo.Name);
var startWith = value.StartsWith("%");
var endsWith = value.EndsWith("%");
if (startWith)
value = value.Remove(0, 1);
if (endsWith)
value = value.Remove(value.Length - 1, 1);
var constant = Expression.Constant(value);
Expression exp;
if (endsWith && startWith)
{
exp = Expression.Call(member, ContainsMethod, constant);
}
else if (startWith)
{
exp = Expression.Call(member, EndsWithMethod, constant);
}
else if (endsWith)
{
exp = Expression.Call(member, StartsWithMethod, constant);
}
else
{
exp = Expression.Equal(member, constant);
}
return Expression.Lambda<Func<TSource, bool>>(exp, param);
}
public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value)
{
return source.Where(LikeExpression(parameter, value));
}
private static PropertyInfo GetPropertyInfo(Expression expression)
{
var lambda = expression as LambdaExpression;
if (lambda == null)
throw new ArgumentNullException("expression");
MemberExpression memberExpr = null;
switch (lambda.Body.NodeType)
{
case ExpressionType.Convert:
memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
break;
case ExpressionType.MemberAccess:
memberExpr = lambda.Body as MemberExpression;
break;
}
if (memberExpr == null)
throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");
var output = memberExpr.Member as PropertyInfo;
if (output == null)
throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");
return output;
}
}
要使用它,您只需在将Contains函数放入的地方添加Like函数即可.您可以在下面查看示例
To use it you you just simply add Like function where you would put the Contains functions. You can see below for a example
using (CustomerEntities customerContext = new CustomerEntities())
{
IQueryable<Customer> customer = customerContext.Customer.Like(x => x.psn, "%1%");
}
这将创建一个看起来像这样的sql查询.
This will create a sql query that looks something like this.
SELECT
[Extent1].[psn] AS [psn]
FROM [dbo].[Customer] AS [Extent1]
WHERE [Extent1].[psn] LIKE '%1%'
这篇关于LINQ使用“喜欢"而不是“(((NVL(INSTR(x,y),0))= 1)"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!