У меня проблема с возвратом значения по умолчанию DateTime
из сложного Linq-to-Sql
запроса.
Надеюсь, следующий упрощенный пример показывает проблему (хотя я не запускал этот точный код):
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
ОБНОВЛЕНИЕ
Хорошо, я не уверен, что моего приведенного выше примера было достаточно для иллюстрации проблемы.Я полагаю, что ошибка может быть связана с тем, как я пытаюсь выполнить подзапрос для третьей связанной таблицы.
В следующем примере воссоздается точная ошибка:
Итак, у меня есть машина, которую я могу отвезти к механику, которая иногда (но не всегда) обслуживается механиком.
Требуется найти через запрос ктаблица машин сколько посещений механика было за каждую машину с момента последнего обслуживания.Проблема в том, что автомобиль никогда не обслуживался, поэтому данные выглядят следующим образом:
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 ненулевому типу, где мне нужно вернуть DateTime.MinValue
или SqlDateTime.MinValue
, когда дата равна нулю (так что я могу сделать фактическуюзапрос, который является числом посещений механика с момента последнего обслуживания)
SOLUTION
Я использовал вариант, предложенный Джоном Скитом, используя приведение к 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();
Обратите внимание на использование конструктора paramatered для даты "по умолчанию" - DateTime.MinValue
здесь не может использоваться, так как он выдает исключение вне диапазона при преобразовании в SQLи SqlDateTime.MinValue
нельзя использовать, так как он не обнуляется (поэтому оператор coalesce становится недействительным).
Я до сих пор не совсем понимаю, почему произошла первоначальная ошибка, и это решение чувствуетнемного хак, буt Я не смог найти более аккуратный способ исправить это.