Linq查找Firstname和Lastname

huangapple go评论89阅读模式
英文:

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[] { &quot;Joe&quot;, &quot;Bloggs&quot;, &quot;Will&quot;, &quot;Green&quot;, &quot;Smith&quot; };

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 =&gt; Expression.Equal(Expression.Property(parameterExpression, &quot;FirstName&quot;), Expression.Constant(x, typeof(string))))
			.Concat(searchPattern.Select(x =&gt; Expression.Equal(Expression.Property(parameterExpression, &quot;LastName&quot;), Expression.Constant(x, typeof(string)))));

All these expressions are then combined with OrElse to a big expression:

var aggregated = expressions.Aggregate((x,y) =&gt; Expression.OrElse(x,y));

We have to convert this BinaryExpression to an Expression&lt;Func&lt;User,bool&gt;&gt; if we want to use it with LINQ:

var expression = Expression.Lambda&lt;Func&lt;User,bool&gt;&gt;(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 = &#39;Joe&#39; instead Firstname like &#39;%Joe%&#39;. 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 =&gt; Expression.Equal(Expression.Call(Expression.Property(parameterExpression, &quot;FirstName&quot;), typeof(string).GetMethod(&quot;Contains&quot;), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool))))
			.Concat(searchPattern.Select(x =&gt; Expression.Equal(Expression.Call(Expression.Property(parameterExpression, &quot;LastName&quot;), typeof(string).GetMethod(&quot;Contains&quot;), new Expression[] { Expression.Constant(x, typeof(string)) }), Expression.Constant(true, typeof(bool)))));

Online-demo: https://dotnetfiddle.net/cM0tz0

huangapple
  • 本文由 发表于 2023年7月3日 12:55:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76601928.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定