【问题标题】:Convert IQueryable from IOrderedQueryable从 IOrderedQueryable 转换 IQueryable
【发布时间】:2019-12-19 23:46:13
【问题描述】:

我正在使用 IQueryable 接口设置 CreateFilteredQuery。我必须返回一个 IQueryable 值,但我通过 OrderBy 函数获得了 IOrderedQueryable。有没有办法将该订单的所有合理数据(不是订单格式和那些不必要的数据)复制到 IQueryable 中?

我几乎尝试了所有方法。我无法更改返回值,因为这些函数也适用于另一个“过滤器”。

我正在尝试对最初是字符串列但填充了数字的列进行排序,因此我必须先解析为 Int,然后再解析为 orderby。 (如果我不这样做,如果我订购结果将是:1 2 20 22 3 而不是 1 2 3 20 22)

我用base.CreateFilteredQuery(input) 创建了“tareas”,并尝试在解析为 int 之前按 externalId 排序

if (input.Sorting == "externalId asc")
{
    var tareasOrdenadas = (tareas.ToList()).OrderBy(t => int.Parse(t.ExternalId));
    return tareasOrdenadas;
}

我期望System.Data.Entity.DbSetIQueryable 的输出。直到现在我有System.Linq.OrdenedEnumerable 或者只是IOrderedEnumerable

PD:当我在其他过滤器中修改“tareas”时,我有一个“System.Linq.IQueryable 类型的 System.Data.Entity.Infrastructure.DbQuery 值”

我需要一个 IQueryable 类型,而不是 IOrderedEnumerable,AsQueryable() 不起作用

PD2:谢谢大家的帮助。很抱歉没有回复,我几天不在办公室。我会尽你所能,谢谢大家。

快乐编码

【问题讨论】:

  • 我不明白你的问题。请edit 并包括minimal reproducible example
  • 此代码将从内存中tareas 后面的表中读取所有内容,并尝试在本地对其进行排序。你为什么不只使用tareas.OrderBy(t->t.ExtenralId) 呢?如果ExternalId 是一个字符串而不是一个数字,那么这是一个需要修复的错误。 011 因为数字相同,而 字符串 完全不同
  • 是否有原因 ExternalId 不是数据库模式中的 int 类型?如果可以解析所有 ExternalId,请在架构级别解决问题,然后在 EF 模型中解决问题,然后您就不必执行 ToList() 或 Parse(),整个问题都会消失。
  • 为什么ExternalId 是一个字符串?这将允许重复数字,例如 001011。如果这是可以接受的,那么在 SQL 中使用 numeric 排序是没有意义的。所有这些 ID 将以随机顺序出现,此时 SQL 将根据 001011 应用正确的字母顺序
  • 真正的问题是排序。如果先按长度排序,然后再按字符串值排序,则相当于数字排序(如果没有前导零),您可以返回 IQueryable

标签: c# linq iqueryable


【解决方案1】:

您可以在 IEnumerable 序列上调用 .AsQueryable(),它会返回 IQueryable

【讨论】:

  • 虽然这将允许编译,但它只会掩盖ToList() 引起的错误。没有可查询的了,整个表已经加载到内存中了。
  • 我认为问题正是要解决编译问题。在查询之前或之后收集数据大致取决于上下文,我无法确定删除 ToList() 是否是一个好的答案。
  • 那是另一回事:IOrderedQueryable 继承自 IQueryable。不应该有任何编译问题。如果有人在OrderBy 之后将无法使用任何 LINQ 运算符。我怀疑 OP 混淆了 IOrderedEnumerable 和 IOrderedQueryable
  • OrderBY 在 List 上返回 IOrderedEnumerable 而不是 IOrderedQueryable。给定的示例是合法的,无法编译。
  • 我说的是问题本身,它询问如何转换Convert IQueryable from IOrderedQueryable。我怀疑 OP 混淆了枚举和查询
【解决方案2】:

您可以在数据库中编写一个 db 函数来将字符串转换为整数(因为没有任何内置功能)并在您的 linq 查询中使用该函数在您订购时将该字符串值转换为整数。这样你就不必调用 .ToList() 方法

类似的东西

if (input.Sorting == "externalId asc")
{
   // you can easily return IOrderedQueryable as IQueryable
   retrun  tareas.OrderBy(t => context.YourDBFunction(t.ExternalId));
}

【讨论】:

    【解决方案3】:

    我认为您的根本问题是需要 IQueryable 返回类型。我假设目的是能够在基本查询中添加额外的数据库级操作(排序、过滤)。这里的问题是IQueryable 提供程序支持有限的一组操作,因此您经常必须转义数据库层(我会为此使用AsEnumerable() 而不是ToList(),顺便说一句)来应用内存操作。一旦你这样做了,就没有办法回到数据库层了。

    如果您将预期的返回类型更改为IEnumerable,您应该会丢失编译错误。

    另一种选择是通过使用Convert.ToInt32 而不是int.Parse 留在数据库层:

    if (input.Sorting == "externalId asc")
    {
        var tareasOrdenadas = tareas.OrderBy(t => Convert.ToInt32(t.ExternalId));
        return tareasOrdenadas;
    }
    

    【讨论】:

    • 您不认为这会引发此错误“LINQ to Entities 无法识别方法 'Int32 ToInt32(System.Object)”吗?
    • @WamiqRehman 从我读过的内容来看,EF5 及更高版本会将其转换为 SQL 中的 CAST 表达式,但是是的,它可能会遇到与 int.Parse 相同的问题。
    • EF-core 将其转换为 CONVERT(int, [ColumnName]),而 EF6 不会。可悲的是,即使是 LINQ-to-SQL 也能做到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    相关资源
    最近更新 更多