【问题标题】:The LINQ expression "could not be translated"LINQ 表达式“无法翻译”
【发布时间】:2021-12-28 03:23:12
【问题描述】:

我已将我的应用程序从 dotNet core2.1 迁移到 Dotnet core5。以下功能已停止工作。我尝试调试代码,但找不到解决方案。给出错误的行是X => Convert.ToInt32(X.Value)。如果我不这样做,转换功能可以正常工作,但列表的顺序会受到干扰。

错误:-

The LINQ expression 'DbSet<EbDepartmentMsts>()\r\n .OrderBy(e => Convert.ToInt32(e.DeptCode.ToString()))' could not be translated. Additional information: Translation of method 'object.ToString' failed. If this method can be mapped to your custom function, Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'

功能

public List<SelectListItem> GetDepartmentCode()
        {
            var table = new List<SelectListItem>();
            try
            {
                table = (from eb in _context.EbDepartmentMsts

                         select new SelectListItem
                         {
                             Text = string.Concat(eb.DeptCode.ToString(), "~", eb.Description),
                             Value = eb.DeptCode.ToString()
                         }).OrderBy(X => Convert.ToInt32(X.Value)).ToList();

            }catch(Exception ex)
            {

            }
            return table;
        }

【问题讨论】:

  • 物化 LINQ 查询然后Selectfrom eb in _context.EbDepartmentMsts.ToList().
  • @YongShun 但是当我使用 .net core sdk 2.1 时,相同的代码更早地工作了

标签: c# linq .net-core


【解决方案1】:

您需要分三步完成:

  1. 仅将必填字段投影到匿名类型中,如果有任何过滤条件,则此处也应包括在内。 在很多情况下也可以包含排序标准!

    select new { eb.DeptCode, eb.Description }

  2. 通过.ToList()IQueryable 中的LINQ 查询具体化为IEnumerable。这会将结果带入内存以供本地客户端执行

    .ToList()

  3. 执行.Select() 将结果投影到SelectListItem。这是在 C# 客户端中执行的,因此您还可以使用您可能需要的任何框架或自定义方法。

       .Select(x => new SelectListItem
       {
           Text = string.Concat(x.DeptCode.ToString(), "~", x.Description),
           Value = x.DeptCode.ToString()
       })
    

有许多解决方案建议“只需将.Tolist() 放入您的查询中”,但重要的是我们尽可能最好地利用数据库并通过投影到临时匿名类型来最小化返回的数据。它不必匿名,但这会减少维护工作并为您提供最大的灵活性。

这是在客户端执行排序的示例:

table = (from eb in _context.EbDepartmentMsts
         select new { eb.DeptCode, eb.Description }
        )
        .ToList()
        .Select(x => new SelectListItem
        {
            Text = string.Concat(x.DeptCode.ToString(), "~", x.Description),
            Value = x.DeptCode.ToString()
        })
        .OrderBy(x => Convert.ToInt32(x.Value))
        .ToList();

或者,您也可以在数据库查询中执行排序:

table = (from eb in _context.EbDepartmentMsts
         orderby eb.DeptCode
         select new { eb.DeptCode, eb.Description }
        )
        .ToList()
        .Select(x => new SelectListItem
        {
            Text = string.Concat(x.DeptCode.ToString(), "~", x.Description),
            Value = x.DeptCode.ToString()
        })
        .ToList();

【讨论】:

  • 虽然这行得通,但一般来说,对 "Materialize First" 的建议太笼统不是很好,您所做的是制定一个 近似的表达式 所需的结果,那么您在执行最终投影之前已将其具体化。这是解决此类问题的 100% 最佳实践方法。对于 OP 在下一个场景中正确应用于此的推理有点模糊。
  • 是的,谢谢你的建议。使用this answer 中提到的支持的函数在具体化数据之前制定表达式会很好。无论如何,感谢知识分享。 =)
  • 感谢您提供的链接,这是传奇!
猜你喜欢
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 2021-11-27
  • 2022-10-20
  • 2020-09-29
  • 2021-07-01
  • 1970-01-01
相关资源
最近更新 更多