使用 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 转换为字符串?
使用 LINQ 在一行代码中将 string[] 转换为 int[]
如何使用 linq 将 DATETIME 类型的列转换为字符串