linq orderby issue(按自定义规则排序字符串)

时间:2012-05-24 19:29:22

标签: c# linq linq-to-sql sql-order-by

我有一个linq查询,没有按照我想要的方式排序。

查询:

return (from obj in context.table_orders
    orderby obj.order_no
    select obj.order_no.ToString() + '-' + obj.order_description).ToList<string>();

我的记录是按字母顺序排列的,有没有我可以使用的Linq关键字,所以我的记录是正确排序的(所以订单30在订单100之前出现)?

我希望结果是字符串列表,因为它用于填充ComboBox。

DB中的一些'order_no'也像'2.10'和'9.1.1'。

5 个答案:

答案 0 :(得分:3)

  

我的记录是按字母顺序排列的,是否有我可以使用的Linq关键字,所以我的记录是   正确订购(所以订单#30出现在订单#100之前)?

如果每次有人问这个我会很富有,我会得到一个中心。

是的,有 - 简单的答案:订购一个数字而不是一个字符串。

  

所以订单#30出现在订单#100之前

但是#30在#100之后出现的原因很简单,因为它们按字母顺序排序,因为它们是字符串。

解析字符串,将数字转换为 - well - 数字,然后按顺序排序。

WHOEVER认为order_no应该是一个没有固定长度的字符串(如00030)应该 - 好 - ;)获得数据库建模的基础教育。我真的很喜欢发票编号等字符串(它们不是数字),但保持它们(a)一个可靠的模式和(b)校验和(以便容易捕获数据输入错误)应该是基础;)

这是初级人员定义数据库和数据模型而不考虑后果的问题。

你有些痛苦 - 解析字符串,通过解析结果来命令。

答案 1 :(得分:0)

如果obj.order_no是字符串,则将其转换为用于排序的数字

orderby Int32.Parse(obj.order_no)

orderby Decimal.Parse(obj.order_no)

原因仅当字符串表示有效数字时才有效。


如果order_no不是有效数字(例如"17.7-8A"),则编写一个将其格式化为包含右对齐数字的函数,例如"00017.007-0008A"并使用此函数排序

orderby FormatOrderNo(obj.order_no)

<强>更新

由于您正在使用EF,因此无法在查询的EF部分中调用此函数。将EF结果转换为IEnumerable<T>并使用LINQ-To-Objects

执行排序
return (from obj in context.table_orders select ...)
    .AsEnumerable()
    .OrderBy(obj => FormatOrderNo(obj.order_no))
    .ToList();

答案 2 :(得分:0)

根据你所说的 - 数字不是真正的数字而是自定义序列标识符(即你甚至不知道你获得了什么样的深度)我会建议实现自定义比较器。

如果你这样做,你可以定义你想要的东西 - 这就是我相信的东西:

  • .
  • 上拆分字符串
  • 比较序列直到并包括较短序列的array.length
  • 如果序列较短且现在有一个平局,请在较长时间之前选择较短的(即2.1之前的2.1.1
  • 如果两个序列的长度相同,则在比较结束时您应该知道哪个序列“更大”
  • 解决。

如果您在IComparer实施时需要灵感,请执行以下示例:
http://zootfroot.blogspot.co.uk/2009/09/natural-sort-compare-with-linq-orderby.html

答案 3 :(得分:0)

如果可能,我会更改数据类型,或者如果适用,将其添加为另一个firld。 如果这是一个禁忌你可以看看其他人在这个问题中提到的解决方案,但要注意 - .ToList()选项适用于小型表,如果你从他们那里取出所有东西但是习惯它会最终给你一个痛苦的世界。从长远来看,你不想获得所有东西,要么使用Where或顶级标准。

其他解决方案很不错,但为了完成任务我的品味很复杂。

你可以通过LinqToSql直接拍摄sql。 http://msdn.microsoft.com/en-us/library/bb399403.aspx

在sql中,您可以随意转换和排序。有些人认为这是一个好主意,有些人会告诉你它很糟糕。你失去了强大的打字和获得性能。你必须知道为什么你采取这种决定,这是最重要的事情。

答案 4 :(得分:0)

由于没有人想出一个可以转换为SQL的自定义orderby函数,所以我选择了IComparer函数:

    public class OrderComparer<T> : IComparer<string>
    {
        #region IComparer<string> Members

        public int Compare(string x, string y)
        {
            return GetOrderableValue(x.Split('-').First()).CompareTo(GetOrderableValue(y.Split('-').First()));
        }
        #endregion

        private int GetOrderableValue(string value)
        {
            string[] splitValue = value.Split('.');
            int orderableValue = 0;
            if (splitValue.Length.Equals(1))
                orderableValue = int.Parse(splitValue[0]) * 1000;
            else if (splitValue.Length.Equals(2))
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100;
            else if (splitValue.Length.Equals(3))
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100 + int.Parse(splitValue[2]) * 10;
            else
                orderableValue = int.Parse(splitValue[0]) * 1000 + int.Parse(splitValue[1]) * 100 + int.Parse(splitValue[2]) * 10 + int.Parse(splitValue[3]);

            return orderableValue;
        }
    }

这些值最多有4个级别。 任何人都有推荐?