微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – LINQ使用“like”而不是“((NVL(INSTR(x,y),0))= 1)”

当使用.Contains()/.StartsWith()/.EndsWith()时,生成sql如下所示:

((NVL(INSTR(x,y),0))= 1)

有没有办法使用它:

LIKE 'x%' or '%x%' or '%x'

因为在查询的执行计划中这两者之间存在巨大的成本差异(44 000 vs 30).

解决方法

当我环顾abit时,我发现了 LIKE operator in LINQ,其中有一些很好的例子说明你可以做到这一点.我测试了下面的链接,来自上面的链接

这是adobrzyc发布的使用Like with lambda的扩展

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;
        }
    }

要使用它,您只需添加Like函数即可放置Contains函数.您可以在下面看到一个示例

using (CustomerEntities customerContext = new CustomerEntities())
            {
                IQueryable<Customer> customer = customerContext.Customer.Like(x => x.psn,"%1%");    
            }

这将创建一个类似于此的SQL查询.

SELECT 
[Extent1].[psn] AS [psn]
FROM [dbo].[Customer] AS [Extent1]
WHERE [Extent1].[psn] LIKE '%1%'

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐