C# 在LINQ Where子句中使用NaturalSortComparer
假设我有一个表Table1,其中有一个字符串字段[ProductString],其中包含以下值: 字母、字母数字或数字:例如ABC、B4、U2、C5、100、U1、U5、U6、U11 我希望能够获取像“ProductString>=U5”这样的where子句,并将其作为字符串传递给LINQ语句,以便它进行计算C# 在LINQ Where子句中使用NaturalSortComparer,c#,linq,C#,Linq,假设我有一个表Table1,其中有一个字符串字段[ProductString],其中包含以下值: 字母、字母数字或数字:例如ABC、B4、U2、C5、100、U1、U5、U6、U11 我希望能够获取像“ProductString>=U5”这样的where子句,并将其作为字符串传递给LINQ语句,以便它进行计算 Table1.Where(t=> t.ProductString >= 'U5'); 通常,这将返回结果U5和U6 但是,我希望能够以某种方式使用,以便返回的结果是U5、U6
Table1.Where(t=> t.ProductString >= 'U5');
通常,这将返回结果U5和U6
但是,我希望能够以某种方式使用,以便返回的结果是U5、U6和U11
我知道如何在OrderBy中使用比较器,因为我希望能够在Where阶段使用它。使用自然排序比较器:
var comparer = new NaturalComparer();
Table1.Where(t=>
comparer.Compare(t.ProductString, "U5") >= 0);
假设您所有的产品字符串都是U%number%格式,那么为什么不滥用这个事实呢
Table1.Where(t=> int.Parse(t.ProductString.Replace("U","")) >= 5);
如果您使用LINQ to Entities,我不确定这是否会编译为存储表达式(即SQL知道如何处理它,我想应该是这样)。如果您经常进行类似的搜索,那么最好的做法是在表中添加两个新字段,[ProductCode]&[ProductNumber]将[ProductString]的两个部分分开 然后你会变成:
Table1.Where(t=> t.ProductCode == "U" && t.ProductNumer > 5);
考虑到公认的答案,我有点困惑,这个问题是否与LINQ和实体相关。接受的答案似乎不是一个在LINQtoEntities上下文中工作的解决方案,但OP对该问题的评论似乎证实了这是在数据库上下文中执行的。无论如何,这个答案专门针对LINQ to实体 我认为在SQLServer中这样做很难,但并非不可能。问题是.NET知道什么是
NaturalSortComparer
,但SQL Server(您希望查询最终发生的地方)没有这样的概念。我能想到的最好的主意包括两个部分:
创建函数Naturalize(@val as nvarchar(max))返回nvarchar(1000)
。有一个非常酷的答案,就是围绕CLR函数创建一个UDF包装器来实现这一点DbContext
创建一个函数映射,该映射将上面的UDF映射到一个可以在EF查询中针对DbContext
调用的函数。大概是这样的:
[DbFunction("MyContext", "Naturalize")]
public static string Naturalize(this string value)
{
throw new NotSupportedException("This function can only be invoked from LINQ to Entities.");
}
归化值来比较字符串:
Table1.Where(t=> t.ProductString.Naturalize() >= "U5".Naturalize());
请记住,UDF将针对查询中包含的每一行执行,这是上例中的整个表。在将函数作为子查询应用之前,您需要确保将查询缩减到可管理的程度。或者,您可能希望尝试对相关表应用某种类型的基于UDF的索引。创建比较器实例,然后使用它…@JeffMercado,但谓词将应用于服务器端。整张桌子都会被取走,我想OP会按照这种方式来做。恐怕存储过程是必要的。@pwas:不清楚源是什么。如果他在之前的查询中使用了这个比较器,那么它可能不是一个数据库。我们可以猜出我们想要的一切,但最终,在他澄清之前,这并不重要。如果这是一个由数据库服务器执行的查询,你不能。这是一个由SQL server数据库执行的查询,它将被合并到ExpressionTree中,但是EF将无法使用NotSupportedException
将其转换为SQL。不能假定字符串是这种格式。它可能只是字母、字母数字或数字:例如ABC、B4、U2、C5、100。我将更新问题使用NaturalComparer
的解决方案是否符合您的要求?实际上需要这样,因为LINQ to Entities不知道比较方法是什么:Table1.AsEnumerable()。其中(t=>comparer.Compare(t.PriorityString,“U5”)>=0);真正的查询远比这更通用:它都是用户驱动的。根据用户选择的过滤器,ProductCode甚至可能不在查询中。和。。它是由用户选择的任意格式。查询可以是((ProductCode>'U5'或类似'%k'的标记)和日期<现在)或(Message='text'和日期<昨天)或其他字符串='100'或优先级