C# 将字符串排序为linq to实体中的数字

C# 将字符串排序为linq to实体中的数字,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,我有像“1”、“2”、“3”、“10”等som字符串,当使用orderby排序列表时是“1”、“10”、“2”、“3”。我想把它们按数字排序,比如1,2,3,…,10。我使用下面的代码对列表进行排序 var model = (from c in General.db.GlbTbComboBases where c.ClassCode.Equals(classCode) select new ReturnData { id = c.BaseCod

我有像“1”、“2”、“3”、“10”等som字符串,当使用orderby排序列表时是“1”、“10”、“2”、“3”。我想把它们按数字排序,比如1,2,3,…,10。我使用下面的代码对列表进行排序

var model = (from c in General.db.GlbTbComboBases
             where c.ClassCode.Equals(classCode)
             select new ReturnData { id = c.BaseCode, name = c.FAName }).OrderBy(c => c.id,
             new SemiNumericComparer());
             if (model.Any())
            {
                CacheManager.cache.GetOrAdd<List<ReturnData>>(key, () => 
                model.ToList<ReturnData>());
                return model.ToList<ReturnData>();
            }

public class SemiNumericComparer : IComparer<string>
        {
            public int Compare(string s1, string s2)
            {
                if (IsNumeric(s1) && IsNumeric(s2))
                {
                    if (Convert.ToInt32(s1) > Convert.ToInt32(s2)) return 1;
                    if (Convert.ToInt32(s1) < Convert.ToInt32(s2)) return -1;
                    if (Convert.ToInt32(s1) == Convert.ToInt32(s2)) return 0;
                }

                if (IsNumeric(s1) && !IsNumeric(s2))
                    return -1;

                if (!IsNumeric(s1) && IsNumeric(s2))
                    return 1;

                return string.Compare(s1, s2, true);
            }

            public static bool IsNumeric(object value)
            {
                try
                {
                    int i = Convert.ToInt32(value.ToString());
                    return true;
                }
                catch (FormatException)
                {
                    return false;
                }
            }
        }

这是一个遗留数据库,我无法更改任何数据类型,因为它可能会在其他应用程序上引发错误。

这里有两个问题:

  • 您正在数据库中以字符串形式存储数字,并且
  • 您正在尝试在Sql Server上执行C#代码
  • 您收到的异常是由于编译器无法将比较逻辑从
    SemiNumericComparer
    类转换为sql查询

    为了达到预期效果,您可以:

    a) 加载内存中的所有数据,并在内存中使用
    SemiNumericComparer
    执行比较,方法是迭代选定的结果,然后按如下顺序排序:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .ToList() // this will load data into memory
                .OrderBy(c => c.id, new SemiNumericComparer());
    
    var model = (from c in General.db.GlbTbComboBases
             where c.ClassCode.Equals(classCode)
             select new { Id = Convert.ToInt32(c.BaseCode), Name = c.FAName })
             .OrderBy(c => c.Id)
            .Select(x => new ReturnData { id = x.Id, name = x.Name });
    
    但是,这不是一个好方法,因为如果数据集非常小,它会增加大量无用的内存消耗,如果数据集在给定时间大于可用内存,则会使应用程序崩溃

    b) 使用将字符串转换为Sql Server上的数字,并使用Sql Server提供的顺序将其作为数字排序:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .OrderBy(c => SqlFunctions.IsNumeric(c.id));
    

    这里有两个问题:

  • 您正在数据库中以字符串形式存储数字,并且
  • 您正在尝试在Sql Server上执行C#代码
  • 您收到的异常是由于编译器无法将比较逻辑从
    SemiNumericComparer
    类转换为sql查询

    为了达到预期效果,您可以:

    a) 加载内存中的所有数据,并在内存中使用
    SemiNumericComparer
    执行比较,方法是迭代选定的结果,然后按如下顺序排序:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .ToList() // this will load data into memory
                .OrderBy(c => c.id, new SemiNumericComparer());
    
    var model = (from c in General.db.GlbTbComboBases
             where c.ClassCode.Equals(classCode)
             select new { Id = Convert.ToInt32(c.BaseCode), Name = c.FAName })
             .OrderBy(c => c.Id)
            .Select(x => new ReturnData { id = x.Id, name = x.Name });
    
    但是,这不是一个好方法,因为如果数据集非常小,它会增加大量无用的内存消耗,如果数据集在给定时间大于可用内存,则会使应用程序崩溃

    b) 使用将字符串转换为Sql Server上的数字,并使用Sql Server提供的顺序将其作为数字排序:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .OrderBy(c => SqlFunctions.IsNumeric(c.id));
    

    如果需要数字顺序,则必须对数字数据类型进行排序:

        string[] str = {"1", "10", "2","011"};
    
        List<string> ordered = str.OrderBy(x => int.Parse(x)).ToList();
    
    string[]str={“1”、“10”、“2”、“011”};
    List ordered=str.OrderBy(x=>int.Parse(x)).ToList();
    
    如果需要数字顺序,则必须对数字数据类型进行排序:

        string[] str = {"1", "10", "2","011"};
    
        List<string> ordered = str.OrderBy(x => int.Parse(x)).ToList();
    
    string[]str={“1”、“10”、“2”、“011”};
    List ordered=str.OrderBy(x=>int.Parse(x)).ToList();
    
    尝试以下方法:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .ToList() // this will load data into memory
                .OrderBy(c => c.id, new SemiNumericComparer());
    
    var model = (from c in General.db.GlbTbComboBases
             where c.ClassCode.Equals(classCode)
             select new { Id = Convert.ToInt32(c.BaseCode), Name = c.FAName })
             .OrderBy(c => c.Id)
            .Select(x => new ReturnData { id = x.Id, name = x.Name });
    

    只需添加一个匿名类型进行排序,然后转换为所需类型。当然,这需要更多的内存。

    尝试以下方法:

    var model = (from c in General.db.GlbTbComboBases
                 where c.ClassCode.Equals(classCode)
                 select new ReturnData { id = c.BaseCode, name = c.FAName })
                .ToList() // this will load data into memory
                .OrderBy(c => c.id, new SemiNumericComparer());
    
    var model = (from c in General.db.GlbTbComboBases
             where c.ClassCode.Equals(classCode)
             select new { Id = Convert.ToInt32(c.BaseCode), Name = c.FAName })
             .OrderBy(c => c.Id)
            .Select(x => new ReturnData { id = x.Id, name = x.Name });
    

    只需添加一个匿名类型进行排序,然后转换为所需类型。当然,它需要更多的内存。

    看起来您正在以字符串的形式存储数字。根据需要将它们存储为int或decimal,然后它将为您提供所需的内容。这称为“自然排序顺序”。有一个相对简单的方法可以做到这一点。非常感谢Martin。看起来您正在以字符串的形式存储数字。根据需要将它们存储为int或decimal,然后它将为您提供所需的内容。这称为“自然排序顺序”。有一个相对简单的方法,非常感谢马丁。