在LINQ Where子句中使用NaturalSortComparer

时间:2014-09-11 07:15:25

标签: c# linq

假设我有一个表Table1,其字符串字段为[ProductString],其值​​为: Alpha,字母数字或数字:例如ABC,B4,U2,C 5,100,U1,U5,U6,U11

我希望能够获取类似“ProductString> = U5”的where子句,并将其作为字符串传递给LINQ语句,以便进行评估

Table1.Where(t=> t.ProductString >= 'U5');

通常这会返回结果U5和U6。

但是,我希望能够以某种方式使用NaturalSortComparer,以便返回的结果是U5,U6和U11。

我知道如何在OrderBy中使用比较器,因为我希望能够在Where阶段使用它。

3 个答案:

答案 0 :(得分:1)

使用自然排序比较器:

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知道如何处理它 - 我想应该这样做。)

答案 1 :(得分:1)

考虑到已接受的答案,我对这个问题是否与LINQ to Entities有关而感到有些困惑。接受的答案似乎不是一个可以在LINQ to Entities上下文中使用的解决方案,但OP对问题的评论似乎证实这是在数据库上下文中执行的。无论如何,这个答案专门针对LINQ to Entities。

我认为在SQL Server中这样做很难,但并非不可能。问题是.NET知道NaturalSortComparer是什么,但SQL Server(你最终想要查询的地方)没有这样的概念。我能想到的最好的想法包括两部分:

  1. 在SQL Server中创建一个UDF(用户定义函数),该UDF将提供可通过自然排序订购的产品:CREATE FUNCTION Naturalize(@val as nvarchar(max)) RETURNS nvarchar(1000)。有一个非常酷的答案here,它围绕CLR函数创建一个UDF包装器来实现这一点。
  2. 接下来为您的DbContext创建一个函数映射,将上面的UDF映射到可以在DbContext的EF查询中调用的函数。像这样:

    [DbFunction("MyContext", "Naturalize")]
    public static string Naturalize(this string value)
    {
        throw new NotSupportedException("This function can only be invoked from LINQ to Entities.");
    }
    
  3. 一旦你掌握了这两个部分,你就可以在实体查询中使用这个新函数,在比较中使用Naturalized值来比较字符串:

    Table1.Where(t=> t.ProductString.Naturalize() >= "U5".Naturalize());
    

    请记住,UDF将针对查询中包含的每一行执行,即上例中的整个表。在将该函数作为子查询应用之前,您需要确保将查询削减为可管理的内容。或者您可能想尝试在相关表上应用某种类型的基于UDF的索引。

答案 2 :(得分:0)

如果您要进行这样的搜索,那么最好的办法是在表格中添加两个新字段,[ProductCode]& [ProductNumber]分隔[ProductString]的两个部分。

然后你比较变成:

 Table1.Where(t=> t.ProductCode == "U" && t.ProductNumer > 5);