Linq to SQL - 如何将数字作为字符串排序?

时间:2011-08-25 00:45:32

标签: .net linq-to-sql

我有一个SQL varchar列,其值为100,2000和S5000。我希望它们按数字顺序排序,而不是按字母顺序排列。如果有字符串字符,我很高兴字符被忽略或出现在排序顺序中的数值之后。

在T-SQL中我可以这样做:

SELECT * FROM tbl
ORDER BY
  CASE
    WHEN ISNUMERIC(fld) = 1 THEN CONVERT(INT, fld)
    ELSE 2147483647
    END ASC,
  fld ASC

我想知道是否有办法在Linq to SQL中执行此操作?

否则我想我的选择是直接执行查询,或者创建一个计算列,其值为00000100,00002000,000S5000等。

编辑:虽然我不确定它的效率如何,但我找到了解决方案。

from s in q
orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending
select s;

3 个答案:

答案 0 :(得分:2)

虽然我不确定它的效率如何,但我找到了解决方案。

from s in q orderby (SqlMethods.Like(s.fld, "%[^0-9]%") ? Int32.MaxValue : Convert.ToInt32(s.fld)) ascending, s.fld ascending select s; 

答案 1 :(得分:1)

如果您已经从数据库中返回了结果,并且您很乐意在内存中进行排序,那么这是一种方法。

首先,定义一个可以在linq-to-objects查询中使用的tryParse函数:

Func<string, int> tryParse = s =>
{
    int i;
    if (!int.TryParse(s, out i))
    {
        i = int.MaxValue;
    }
    return i;
};

然后进行排序的实际查询很简单:

var query =
    from t in tbls.ToArray() // force the linq-to-sql query to execute
    orderby t.fld
    orderby tryParse(t.fld)
    select t;

简单,是吗?

答案 2 :(得分:0)

我知道问题是关于Linq-to-SQL,但我想我会为任何EF用户提供一个实体框架4答案,他们偶然发现了这个问题,寻找在该框架内完成此任务的方法。我没有使用Linq-to-SQL的经验,因此,据我所知,这实际上也可以在那里工作(但我对此表示怀疑)。

Dim results = (From item in ctx.tbl
               Let sortValue = If(SqlFunctions.IsNumeric(item.fld) = 1, CInt(item.fld), 2147483647)
               Order By sortValue).ToList()

这大致转变为此商店查询:

SELECT [Project1].*
FROM ( SELECT 
    [Extent1].*
    CASE WHEN (1 = (ISNUMERIC([Extent1].[Value]))) THEN  CAST( [Extent1].[Value] AS int) ELSE 99999999 END AS [C2]
    FROM [dbo].[tbl] AS [Extent1]
)  AS [Project1]
ORDER BY [Project1].[C2] ASC

此解决方案利用System.Data.Objects.SqlClient.SqlFunctions基本直接调用查询中的SQL ISNUMERIC function。我想指出IsNumeric将返回1 甚至是小数,并将“十进制”varchar转换为int会导致问题。 CDbl()而不是CInt()值可能是最安全的,除非您知道您的数据永远不会是“int”varchar。