为什么我不能在LinQ查询中将可空的DateTime转换为字符串?

mat*_*360 8 linq datetime nullable

我试图获取DateTime值,如果它不为null,则返回短时间字符串.我的查询如下所示:(TimeIn不可用,而TimeOut为NULLABLE)

    var times = from t in db.TimePostings
                where t.MemberID == member.MemberID
                select new
                {
                    Date = t.TimeIn.ToShortDateString(),
                    TimeIn = t.TimeIn.ToShortTimeString(),
                    TimeOut = t.TimeOut.HasValue ? t.TimeOut.Value.ToShortTimeString() : "-------"
                };
gvTimePostings.DataSource = times;
gvTimePostings.DataBind();
Run Code Online (Sandbox Code Playgroud)

但是当我尝试使用错误进行数据绑定时,这会失败:

无法翻译表达式'Table(TimePosting).Where(t =>(t.MemberID == Invoke(value(System.Func 1[System.String])))).Select(t => new <>f__AnonymousType84(Date = t.TimeIn.ToShortDateString(),TimeIn = t.TimeIn.ToShortTimeString(), TimeOut = IIF(t.TimeOut.HasValue,(t.TimeOut ?? Invoke(value(System.Func`1 [System.DateTime]))).ToShortTimeString(),"-------"),小时=""))'进入SQL并且不能将其视为本地表达式.

如果我尝试使用,我也会收到类似的错误:

TimeOut = t.TimeOut.HasValue ? Convert.ToDateTime(t.TimeOut).ToShortTimeString() : "-------"
Run Code Online (Sandbox Code Playgroud)

但是,如果我将TimeOut属性更改为:

TimeOut = t.TimeOut.HasValue ? t.TimeOut.ToString() : "-------",
Run Code Online (Sandbox Code Playgroud)

它工作正常,但不像我想要的那样格式化时间(shortTimeString).

那是怎么回事?

Jon*_*eet 9

正如其他人所说,问题在于尝试将ToShortDateStringetc 转换为SQL.幸运的是,这很容易解决:用SQL 获取数据,然后在.NET中格式化:

var timesFromDb = from t in db.TimePostings
                  where t.MemberID == member.MemberID
                  select new { t.TimeIn, t.TimeOut };

var times = from t in timesFromDb.AsEnumerable()
            select new
            {
                Date = t.TimeIn.ToShortDateString(),
                TimeIn = t.TimeIn.ToShortTimeString(),
                TimeOut = t.TimeOut.HasValue 
                                     ? t.TimeOut.Value.ToShortTimeString() 
                                     : "-------"
            };
Run Code Online (Sandbox Code Playgroud)

AsEnumerable()这里的调用基本上意味着,"停止尝试使用SQL处理查询;在LINQ to Objects中完成剩下的工作".

  • @ matthew_360:效果不一样,没有 - `ToList()`必须建立所有项目的列表,而不是流式传输它们.如果你要在多个地方使用`times`而没有缓冲**结果,那是好的,但是我认为没有理由建立缓冲区 - 我个人会使用`AsEnumerable`,它仅用于*目的你想要:从`IQueryable <T>`转换为`IEnumerable <T>`. (2认同)

Jus*_*ner 6

ToShortTimeString()在SQL中没有翻译.因此,将语句转换为单个SQL语句失败并抛出异常.

如果你将语句分成两个调用(一个用于检索数据而另一个用于创建投影),那么事情就可以了:

// must call ToList to force execution of the query before projecting
var results = from t in db.TimePostings
              where t.MemberID == member.MemberID
              select new { t.TimeIn, t.TimeOut };

var times = from t in results.AsEnumerable()
            select new
            {
                Date = t.TimeIn.ToShortDateString(),
                TimeIn = t.TimeIn.ToShortTimeString(),
                TimeOut = t.TimeOut.HasValue ? 
                    t.TimeOut.Value.ToShortTimeString() :
                    "-------"
            };
Run Code Online (Sandbox Code Playgroud)