我在返回默认值时遇到问题DateTime
复合体的价值Linq-to-Sql
query.
希望下面的简化示例能够显示问题(尽管我还没有运行这个确切的代码):
users.Select(u =>
new MyDomainObject(
u.Id,
u.Transactions
.Where(t => false) // empty results set
.Select(t => t.TransactionTime) // TransactionTime is DATETIME NOT NULL
.OrderByDescending(x => x)
.FirstOrDefault() // I want DateTime.MinValue (or SqlDateTime.MinValue)
)
);
所以我想要最后一个时间戳,或者一些MinValue
如果没有结果,则显示时间戳。
枚举上面的查询会给出错误
The null value cannot be assigned to a member with type System.DateTime
UPDATE
好吧,我不确定上面的例子是否足以说明问题。我相信该错误可能与我尝试在第三个链接表上执行子查询的方式有关。
以下示例重新创建了确切的错误:
所以我有一辆车,我可以把它带到机械师那里,有时(但并非总是)由机械师维修。
要求是找到通过查询 car 表自上次维修以来,每辆车已接受过多少次机械师上门服务。问题是当汽车从未维修过时,因此数据如下所示:
Car
-------------
Id: 1
MechanicVisit
-------------
Id: 1
CarId: 1
ServiceRecordId: NULL
VisitDate: 1 Jan 2011
ServiceRecord
-------------
<empty>
因此,显示错误的一个简单示例是获取上次服务时间列表的查询:
var test = _dataContext.GetTable<Car>
.Select(c =>
c.MechanicVisits
.Select(m => m.ServiceRecord)
.Select(s => s.ServiceDate)
.OrderByDescending(d => d)
.FirstOrDefault()
).ToList();
这给出了前面描述的尝试将 null 分配给不可为 null 的类型的错误,我需要做的是 returnDateTime.MinValue
or SqlDateTime.MinValue
当日期为空时(这样我可以进行实际查询,即自上次服务以来机械师访问的次数)
SOLUTION
我使用了 Jon Skeet 建议的变体,使用演员阵容DateTime?
和空合并运算符:
var test = _dataContext.GetTable<Car>
.Select(c =>
c.MechanicVisits
.Select(m => m.ServiceRecord)
.Select(s => (DateTime?)s.ServiceDate)
.OrderByDescending(d => d)
.FirstOrDefault() ?? new DateTime(1900, 1, 1)
).ToList();
请注意“默认”日期的参数化构造函数的使用 -DateTime.MinValue
不能在这里使用,因为它在转换为 SQL 时会抛出超出范围的异常,并且SqlDateTime.MinValue
不能使用,因为它不可为空(因此合并运算符变得无效)。
我仍然不太明白为什么会发生最初的错误,并且这个解决方案确实感觉有点老套,但我一直无法找到任何更简洁的方法来修复它。