0

我有一个 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。

数据库中的一些“order_no”也像“2.10”和“9.1.1”。

4

5 回答 5

3

会发生什么情况是我的记录按字母顺序排序,是否有我可以使用的 Linq 关键字,以便我的记录正确排序(所以订单 #30 在订单 #100 之前)?

如果每次有人问这个我都能得到一分钱,我会很富有。

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

所以订单#30在订单#100之前)

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

解析字符串,将数字转换为 - 好吧 - 一个数字,然后按它排序。

谁想到 order_no 应该是一个没有固定长度的字符串(如 00030)应该 - 好 - ;) 接受数据库建模的基础教育。我真的很喜欢发票号码之类的东西是字符串(它们不是数字),但将它们保持在(a)一个可定义的模式和(b)校验和(以便很容易发现数据输入错误)应该是基础;)

初级人员定义数据库和数据模型而不考虑后果时,就会遇到这种问题。

你有一些痛苦 - 解析字符串,通过解析结果排序。

于 2012-05-24T19:36:05.333 回答
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 结果转换为 anIEnumerable<T>并使用 LINQ-To-Objects 执行排序

return (from obj in context.table_orders select ...)
    .AsEnumerable()
    .OrderBy(obj => FormatOrderNo(obj.order_no))
    .ToList();
于 2012-05-24T19:37:46.473 回答
0

根据你所说的 - 这些数字不是真正的数字,而是自定义序列标识符(即你甚至不知道你得到的深度级别)我建议实现一个自定义比较器。

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

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

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

于 2012-05-24T20:14:30.893 回答
0

如果可能的话,我要么更改数据类型,要么将其添加为另一个文件(如果适用)。如果这是不行的,您可以查看其他人在这个问题中提到的解决方案,但要注意 - 如果您从小表中提取所有内容但习惯它最终会给您一个 .ToList() 选项非常适合小表痛苦的世界。从长远来看,您不想得到所有东西,要么使用 Where 要么使用顶级标准。

其他解决方案很好,但对我来说完成任务的口味很复杂。

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

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

于 2012-05-24T20:21:50.100 回答
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 个级别。有人有推荐吗?

于 2012-05-24T20:39:59.507 回答