【问题标题】:Entity Famework: Select in Linq Problems with Date formats实体框架:在 Linq 中选择日期格式问题
【发布时间】:2016-04-06 18:34:43
【问题描述】:

嗨,我在控制器中有这段代码,这可以很好地转换 Fecha 属性的日期格式

var com = db.Comentario
               .Where(co => co.IdProducto == id)
               .OrderByDescending(c => c.Fecha)
               .Skip((int)offset)
               .Take(2)
               .ToList()
               .Select(c => new {
                   c.Id,
                   Usuario = new {
                       c.Usuario.Nombre,
                       c.Usuario.Apellidos,
                       c.Usuario.Avatar,
                       c.Usuario.Nickname
                   },
                   c.Contenido,
                   Fecha = c.Fecha.ToShortDateString(), //it works fine
                   R = c.IdEstado == 1 ? false : true
               });

但是...问题出在另一个控制器上

        db.Comentario.Add(com);
        db.SaveChanges();

        var resp = db.Comentario
                .Where(c => c.Id == com.Id)
                .Select(c => new {
                    c.Id,
                    Usuario = new {
                        c.Usuario.Nombre,
                        c.Usuario.Apellidos,
                        c.Usuario.Avatar,
                        c.Usuario.Nickname
                    },
                    c.Contenido,
                    Fecha = c.Fecha.ToShortDateString(),//the problem is here
                    R = c.IdEstado == 1 ? false : true
                }).FirstOrDefault();

在这里我向数据库插入了一个 Commentario 对象,我想以 JSON 结果返回该对象,但出现此错误

LINQ to Entities 无法识别方法“System.String ToShortDateString()”方法,并且该方法无法转换为存储表达式。

如果两者是相同的代码,我无法理解为什么代码会失败。 谢谢

【问题讨论】:

  • 在幕后,这些代码片段被不同地解析和处理。第一段代码在 Take() ToList() 操作之后对 DB 执行查询,然后您正在对生成的 List 项执行 Select。此时,您将 Linq 用于可枚举的对象。在第二个代码集中,FirstOrDefault 之前的所有内容都被翻译为 SQL,而 Linq to Entities 不知道如何处理 ToShortDateString(),因为它没有翻译。
  • 不要格式化查询中的日期。让 UI 决定如何显示日期。您不会将ToShortDateString() 附加到您将发送到用户界面的每个日期,是吗?
  • 是的,但是当我发送不带格式的日期时,我得到了“\Date(321654879)/”,我想这是一个 unix 日期,但是当我转换它时,我得到一个不正确的日期
  • 是的,这就是 JSON 序列化默认的方式。我没有说这是微不足道的,但仍然是要走的路。有时您想显示带有时间分量的日期,有时不显示日期,或者您想在需要日期的数据选择器中编辑它们。或者您希望客户文化决定日期的显示方式! Moment.js 在这里有很大的帮助。

标签: c# entity-framework linq lambda


【解决方案1】:

它们不一样...只要您调用.ToList(),您就正在对底层数据存储执行查询。

var com = db.Comentario
               .Where(co => co.IdProducto == id)
               .OrderByDescending(c => c.Fecha)
               .Skip((int)offset)
               .Take(2)
               .ToList() // <<< Your query is being executed here

EntityFramework 轻松将上述所有内容转换为 SQL...Entity Framework 为您检索该数据,在您调用 ToList() 后,数据存储在内存中,这意味着数据已被检索,而您没有更长的查询存储在数据库中的数据,但已经获取的数据。

将其与您的第二个示例进行比较...

    var resp = db.Comentario
            .Where(c => c.Id == com.Id)
            .Select(c => new {   // <<< Here you're still querying the
                c.Id,            //     database, nothing has been received / executed yet.
                Usuario = new {
                    c.Usuario.Nombre,
                    c.Usuario.Apellidos,
                    c.Usuario.Avatar,
                    c.Usuario.Nickname
                },
                c.Contenido,
                Fecha = c.Fecha.ToShortDateString(),

EntityFramework 尚未获取数据,它正在尝试将您的查询转换为 SQL,但您无法将 ToShortDateString() 转换为 SQL。您需要做的是像之前在Where(...)Select(...) 子句之间使用ToList() 一样执行查询。

【讨论】:

  • 我尝试将 ToList() 放在 Where 和 Select 子句之间,但我得到了那个错误,System.NullReferenceException: Object reference not set to an instance of an object . 在这一行:.Select(c => new {
  • 使用断点运行您的方法。我感觉您的 c.Fecha 属性为空
  • 这是结果,Fecha属性不为空,Image
  • 乌萨里奥是罪魁祸首
【解决方案2】:

好消息伙计们,我找到了解决方案,购买我不确定这是否是最好的方法。

      var resp = db.Comentario
                .Include(u=>u.Usuario) // with this Usuario is no longer null
                .Where(c => c.Id == com.Id && c.IdEstado != 3)
                .ToList()
                .Select(c => new {
                    c.Id,
                    Usuario = new {
                        c.Usuario.Nombre,
                        c.Usuario.Apellidos,
                        c.Usuario.Avatar,
                        c.Usuario.Nickname
                    },
                    c.Contenido,
                    Fecha = c.Fecha.ToShortDateString(),
                    R = c.IdEstado == 1 ? false : true
                });

我删除了 FirstOrDefault(),并将 ToList() 放在 Where 和 Select 子句之间

这是我的解决方案 谢谢:D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-24
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多