扩展 Entity Framework支持复杂的过滤条件(多个关键字模糊匹配)

 更新时间:2012年12月27日 15:15:35   作者:  
之前遇到一个棘手的Linq to EF查询的技术问题,现有产品表Product,需要根据多个关键字模糊匹配产品名称, 现将解决方案分享出来,按兴趣的朋友可以参考下
之前遇到一个棘手的Linq to EF查询的技术问题,现有产品表Product,需要根据多个关键字模糊匹配产品名称, 现将解决方案分享出来。

问题描述
根据需求,我们需要编写如下的SQL语句来查询产品
复制代码 代码如下:

select * from dbo.Product
where
(ProductName like 'Product1%' or
ProductName like 'Product2%')

如何将以上的SQL语句转换成EF的写法呢?
方案一
可以使用Union,将以上SQL语句转换成以下的形式:
复制代码 代码如下:

select * from dbo.Product
where
ProductName like 'Product1%'
UNION
select * from DocutapCMS.dbo.Product
where
ProductName like 'Product2%'

然后将上路SQL换成Linq To EF就非常简单了,再此就不贴出来了。但每个条件都要写一个Query,工作量大。如果条件太多,生成的SQL语句也非常大,并且写起来很费力。

方案二
我们从Linq To EF的Contains功能得到启发,Linq To EF 会将Contains转换成IN表达式。
那么我们可不可以直接写Expression,将条件转换成上述SQL语句呢?答案是肯定的。以下就是实现上述方案的具体Linq To EF扩展。
复制代码 代码如下:

public static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector,
  IEnumerable<TValue> values)
{
  var startsWithMethod = typeof (string).GetMethod("StartsWith", new[] { typeof(string) });
  var startWiths = values.Select(value => (Expression)Expression.Call(valueSelector.Body, startsWithMethod, Expression.Constant(value, typeof(TValue))));
  var body = startWiths.Aggregate<Expression>(((accumulate, equal) => Expression.Or(accumulate, equal)));
  var p = Expression.Parameter(typeof(TElement));
  return Expression.Lambda<Func<TElement, bool>>(body, p);
}

用法:
复制代码 代码如下:

private static void QueryProducts(IQueryable<Product> query)
{
var productNames = new string[] {"P1", "P2"};
var query1 = from a in query.Where(BuildContainsExpression<Product, string>(d=>d.ProductName, productNames))
select a;
var items2 = query1.ToList();
}
private static void QueryProducts(IQueryable<Product> query)
{
var productNames = new string[] {"P1", "P2"};
var query1 = from a in query.Where(BuildContainsExpression<Product, string>(d=>d.ProductName, productNames))
select a;
var items2 = query1.ToList();
}

创建扩展方法,让调用变得简单
复制代码 代码如下:

public static IQueryable<TElement> WhereOrLike<TElement, TValue>(this IQueryable<TElement> query,
  Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
{
return query.Where(BuildContainsExpression<TElement, TValue>(valueSelector, values));
}
private static void QueryProducts2(IQueryable<Product> query)
{
var productNames = new string[] {"P1", "P2"};
query.WhereOrLike(d=>d.ProductName, productNames).ToList();
}

通过SQL Profile 监视生成的SQL语句
复制代码 代码如下:

-- Region Parameters
DECLARE @p0 NVarChar(3) = 'P1%'
DECLARE @p1 NVarChar(3) = 'P2%'
-- EndRegion
SELECT [t0].[Id], [t0].[ProductName]
FROM [Product] AS [t0]
WHERE ([t0].[ProductName] LIKE @p0) OR ([t0].[ProductName] LIKE @p1)

相关文章

  • .NET Core中HttpClient的正确打开方式

    .NET Core中HttpClient的正确打开方式

    这篇文章主要给大家介绍了关于.NET Core中HttpClient的正确打开方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • asp.net 页面间传值与跳转的区别

    asp.net 页面间传值与跳转的区别

    通过Server.Transfer("b.aspx") 与Response.Redirect("b.aspx")的区别
    2010-04-04
  • c# datatable用法总结

    c# datatable用法总结

    在项目中经常用到DataTable,如果DataTable使用得当,不仅能使程序简洁实用,而且能够提高性能,达到事半功倍的效果,现对DataTable的使用技巧进行一下总结。
    2010-09-09
  • asp.net中js和jquery调用ashx的不同方法分享

    asp.net中js和jquery调用ashx的不同方法分享

    asp.net中js和jquery调用ashx的不同方法分享,需要的朋友可以参考一下
    2013-06-06
  • ASP.NET内置对象之Application对象

    ASP.NET内置对象之Application对象

    Application对象是HttpApplicationState类的一个实例,它可以产生一个所有Web应用程序都可以存取的变量,这个变量的可以存取范围涵盖全部使用者,也就是说只要正在使用这个网页的程序都可以存取这个变量。
    2008-09-09
  • vs.net控件updatePanel实现无刷新的方法

    vs.net控件updatePanel实现无刷新的方法

    vs.net控件updatePanel实现无刷新的方法,需要的朋友可以参考一下
    2013-04-04
  • asp.net 在客户端显示服务器端任务处理进度条的探讨

    asp.net 在客户端显示服务器端任务处理进度条的探讨

    由于 HTTP 协议本身的无状态性,B/S结构的程序无法像C/S程序那样,实时显示程序处理的进度。搜索一下网上,一般都是采用静态变量保存程序执行进度的方法实现,但是,这种方法是完全错误的,在并发的情况下,多个用户访问一个程序,会造成混乱。
    2009-09-09
  • Asp.net 自带报表的使用详解

    Asp.net 自带报表的使用详解

    最近公司的功能需要使用报表,用的是微软自带的报表,谈一谈我们的做法,希望可以给想学习的人一些指导
    2013-10-10
  • 利用.net代码实现发送邮件

    利用.net代码实现发送邮件

    这篇文章主要为大家详细介绍了利用.net代码实现发送邮件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • ASP.NET Core中间件实现限流的代码

    ASP.NET Core中间件实现限流的代码

    这篇文章主要介绍了ASP.NET Core中间件实现限流的方法,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03

最新评论