英文:
Linq to find Firstname and Lastname
问题
以下是翻译好的内容:
"有人能建议我如何编写LINQ查询来查找具有单个搜索字段的表中的用户吗?
用户可以在UI中的单个文本框中输入'姓名'(例如'Joe Bloggs'或'Will Green Smith')。我想拆分该值并使用'like'功能搜索名字和姓氏列。所以类似于这样:
select * from Users
where
Firstname like '%Joe%' or Firstname like '%Bloggs%'
or Firstname like '%Will%' or Firstname like '%Green%'
or Firstname like '%Smith%'
or Lastname like '%Joe%' or Lastname like '%Bloggs%'
or Lastname like '%Will%' or Lastname like '%Green%'
or Lastname like '%Smith%'
在LINQ中实现相同效果的最佳方法是什么?
谢谢"
英文:
Can anyone suggest how I can write a linq query to find users in a table with a single search field?
Users can enter 'Name' in a single text box in the UI (e.g. 'Joe Bloggs', or 'Will Green Smith'). I want to split that value up and search both Firstname and Lastname columns using 'like' functionality. So something like this:
select * from Users
where
Firstname like '%Joe%' or Firstname like '%Bloggs%'
or Firstname like '%Will%' or Firstname like '%Green%'
or Firstname like '%Smith%'
or Lastname like '%Joe%' or Lastname like '%Bloggs%'
or Lastname like '%Will%' or Lastname like '%Green%'
or Lastname like '%Smith%'
What would be the best way to achieve the same effect in linq?
Thanks
答案1
得分: 1
你可以在运行时构建表达式。我假设你有以下类:
class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
作为输入,你可能有一个类似这样的数组:
var searchPattern = new string[] { "Joe", "Bloggs", "Will", "Green", "Smith" };
然后,我们为searchPattern数组的每个元素创建两个表达式。第一个表达式将字符串与FirstName
属性进行比较,第二个表达式将字符串与LastName
属性进行比较:
var parameterExpression = Expression.Parameter(typeof(User));
var expressions = searchPattern.Select(x => Expression.Equal(Expression.Property(parameterExpression, "FirstName"), Expression.Constant(x, typeof(string))))
.Concat(searchPattern.Select(x => Expression.Equal(Expression.Property(parameterExpression, "LastName"), Expression.Constant(x, typeof(string)))));
然后,将所有这些表达式与OrElse
组合成一个大表达式:
var aggregated = expressions.Aggregate((x, y) => Expression.OrElse(x, y));
如果我们想在LINQ中使用它,我们必须将这个BinaryExpression
转换为Expression<Func<User, bool>>
:
var expression = Expression.Lambda<Func<User, bool>>(aggregated, new ParameterExpression[] { parameterExpression });
在Entity Framework中,可以直接使用它:
var result = context.Users.Where(expression);
如果你使用Linq2Objects,你首先必须创建一个函数:
var result = users.Where(expression.Compile());
该代码将创建一个SQL查询,其中FirstName = 'Joe'
而不是FirstName like '%Joe%'
。如果你想使用like
,表达式会变得更复杂。你将不得不调用字符串类的Contains
方法。这将导致以下表达式(必须像上面一样汇总):
var expressions = searchPattern.Select(x => Expression.Equal(Expression.Call(Expression.Property(parameterExpression, "FirstName"), typeof(string).GetMethod("Contains"), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool))))
.Concat(searchPattern.Select(x => Expression.Equal(Expression.Call(Expression.Property(parameterExpression, "LastName"), typeof(string).GetMethod("Contains"), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool)))));
在线演示:https://dotnetfiddle.net/cM0tz0
英文:
You could build up an expression during runtime. I assume you have the following class:
class User
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
As an input, you might have an array like this:
var searchPattern = new string[] { "Joe", "Bloggs", "Will", "Green", "Smith" };
Then we create two expressions for each element of the searchPattern array. The first expression will compare the string with the FirstName
property, the second expression will compare the string with the LastName
property:
var parameterExpression = Expression.Parameter(typeof(User));
var expressions = searchPattern.Select(x => Expression.Equal(Expression.Property(parameterExpression, "FirstName"), Expression.Constant(x, typeof(string))))
.Concat(searchPattern.Select(x => Expression.Equal(Expression.Property(parameterExpression, "LastName"), Expression.Constant(x, typeof(string)))));
All these expressions are then combined with OrElse
to a big expression:
var aggregated = expressions.Aggregate((x,y) => Expression.OrElse(x,y));
We have to convert this BinaryExpression
to an Expression<Func<User,bool>>
if we want to use it with LINQ:
var expression = Expression.Lambda<Func<User,bool>>(aggregated, new ParameterExpression[] { parameterExpression });
In Entity Framework, this can be used directly:
var result = context.Users.Where(expression);
If you use Linq2Objects, you have to create a function first:
var result = users.Where(expression.Compile());
The code would create a SQL query with Firstname = 'Joe'
instead Firstname like '%Joe%'
. If you want to use like, the expressions will become a bit more complicated. You will have to call the Contains
method of the string class. This will lead to the following expressions (which have to be aggregated as above):
var expressions = searchPattern.Select(x => Expression.Equal(Expression.Call(Expression.Property(parameterExpression, "FirstName"), typeof(string).GetMethod("Contains"), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool))))
.Concat(searchPattern.Select(x => Expression.Equal(Expression.Call(Expression.Property(parameterExpression, "LastName"), typeof(string).GetMethod("Contains"), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool)))));
Online-demo: https://dotnetfiddle.net/cM0tz0
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论