使用 LINQ 将字符串转换为 int 以进行排序

Posted

技术标签:

【中文标题】使用 LINQ 将字符串转换为 int 以进行排序【英文标题】:Convert string to int for ordering using LINQ 【发布时间】:2011-08-24 12:04:55 【问题描述】:

我想通过转换为 int 的字符串来排序我的列表:

var orderedListOfRfidTags = uow.RfidTags.OrderBy(t => Convert.ToInt32(t.Number)).ToList();

但得到:不支持方法“ToInt32”。

【问题讨论】:

你的意思是 LINQ to SQL 还是 EF? 我正在使用 Lightspeed 作为我的 ORM.. 但我猜这可能对所有 linq 供应商都是不可知的? 不,它确实取决于提供商。一些提供商可能支持该方法。 一种选择是尝试使用int.Parse(),但它也可能不起作用。 【参考方案1】:

怎么样:

var orderedListOfRfidTags = uow.RfidTags.OrderBy(t => t.Number).ToList();

删除任何 CLR 方法,以便 ORM 可以将其转换为已知的 SQL 查询

编辑: 我刚读到想先转换它:

var orderedListOfRfidTags = uow.RfidTags.ToList().OrderBy(t => Convert.ToInt32(t.Number));

要么像我之前提到的那样从 DB 中获取所有内容,然后在客户端(linq to object)上对其进行排序,要么在你的 ORM 上找到一个方法来转换为 int 顺序。下单前 选择一个新的列表并转换数字,然后按它排序。

编辑2:

直接转换如何与此 ORM 一起使用?

var orderedListOfRfidTags = uow.RfidTags.OrderBy(t => (int)t.Number).ToList();

【讨论】:

谢谢@PrOfess0rX 问题是 t.Number 作为字符串存储在数据库中。在这种情况下,我知道返回的 t.Numbers 实际上都是数字。如果我使用上面的查询,有序列表会按照字符串的顺序返回,即 1、11、111 等。【参考方案2】:

所以,这是我对这个问题的解决方案:

var query = (from q in query select q).ToList().Where(x => Convert.ToInt32(x.col_string) > 0);

我首先将 IQueryable 转换为一个列表,然后将数据类型 string 的列转换为 int32 以用于数学运算。

我希望这会有所帮助。

【讨论】:

这是一个糟糕的方法:它从后端带来未经过滤的数据并在调用者处对其进行过滤。 如果需要将列转换为字符串才能应用于结果集的过滤器,这是我在 LINQ 中找到的执行操作的唯一方法。可以想象一种情况,您提取结果: var x = _db.Where(x => x.filt_col == somevalue).ToList() 但留下不需要分解和过滤的数据从后端拉出并转换: var a = x.Where(x => Convert.ToInt32(x.col_string) > 0 && Convert.ToInt32(x.col_string) Convert.ToInt32(x.col_string) > 100 && Convert.ToInt32(x.col_string) 【参考方案3】:
var orderedListOfRfidTags = (uow.RfidTags.ToList()).OrderBy(t => int.Parse(t.Number));

【讨论】:

【参考方案4】:

我是 LightSpeed 的开发者之一。

LightSpeed 3.11 RTM 中的 LINQ 提供程序不支持 Convert.ToInt32。不过,我们现在通过夜间版本添加了支持,现在可供下载。

如果您不想使用每晚版本,您可以通过下拉到查询对象 API 并直接调用 SQL CAST 函数来获得所需的结果。这看起来像:

Query query = new Query

  Order = Order.By(Entity.Attribute("Number")
                         .Function("CAST", new LiteralExpression("INTEGER")  EmitInline = true ))
;

uow.Find<RfidTag>(query);

转换类型的 LiteralExpression 相当冗长的原因是默认情况下 LightSpeed 通过参数将值发送到数据库(以避免 SQL 注入攻击)。但是对于 CAST 函数,SQL 引擎需要看到 CAST(Number, INTEGER) 而不是 CAST(Number, @p0) 其中 p0 的值为“INTEGER”。所以你必须使用绕过参数化的 EmitInline 表达式,而不是更自然的字符串文字。

不过,再一次强调,夜间版本确实支持 LINQ 中的 Convert.ToInt32,因此如果您想避免进行夜间构建,只需降级到此级别。

【讨论】:

【参考方案5】:

尝试使用int.Parse 而不是转换。 Lightspeed 很可能支持其中一个而不支持另一个。

var orderedListOfRfidTags = uow.RfidTags
    .OrderBy(t => int.Parse(t.Number))
    .ToList();

【讨论】:

【参考方案6】:

我不确定“RfidTags”是哪种类型,也不熟悉 Lightspeed ORM,但我知道当我遇到 Linq to Sql 类似的问题时,我会告诉我我正在尝试的特定方法不支持在 Where 或 OrderBy 子句中调用,然后我只是改变一些东西,以便我处理普通的旧 Linq。

例如,你能试试这个吗?

var listOfRfidTags = uow.RfidTags.ToList();
var orderedListOfRfidTags = listOfRfidTags.OrderBy(t => Convert.ToInt32(t.Number));

(是的,可以将其合并为一行,但为清楚起见,此处显示为两行。)

祝你好运!

【讨论】:

这将获取 rfidTags 的整个列表,然后在客户端进行排序。如果列表很小,可能没问题。但是,如果操作员想在那时订购前 10 个,因为列表很大,这基本上会执行 SELECT * FROM RFIDTAGS... 并产生很大的性能问题。

以上是关于使用 LINQ 将字符串转换为 int 以进行排序的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能使用 SqlFunctions 在 LinQ 中将 int 转换为字符串?

c#中如何使用split方法

使用 LINQ 在一行代码中将 string[] 转换为 int[]

如何使用 linq 将 DATETIME 类型的列转换为字符串

实体框架 - 荒谬的查询,将 smallint 转换为 int 进行比较 [重复]

从 int 获取单个数字以在 C/C++ 中进行基数排序的最佳方法