Избегайте «Обнуляемый объект должен иметь значение». в Linq-To-Sql

У меня есть такой запрос метода:

public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
    using (var db = new L2SDataContext())
    {
        var result = from bo in db.BusinessObjects
                     where (filterId.HasValue)
                               ? bo.Filter == filterId.value
                               : true
                     orderby bo.Name
                     select SqlModelConverters.ConvertBusinessObject(bo);
        return result.ToList();
    }
}

Во время выполнения это вызывает исключение System.InvalidOperationException: объект, допускающий значение NULL, должен иметь значение.

Если посмотреть на Debugger, проблема в моем предложении Where: Linq To SQL пытается преобразовать все в SQL, поэтому даже если filterId имеет значение NULL, он все равно будет пытаться получить доступ к filterId.value.

Я думал / надеялся, что компилятор C # / CLR оценит это предложение where как блок кода и отправит в Linq To SQL только одну из двух ветвей, но это не так, как это работает.

Моя реорганизованная версия работает, но не очень элегантна:

public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
    using (var db = new L2SDataContext())
    {
        var temp = from bo in db.BusinessObjects select bo;
        if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value);
        var result = from t in temp
                     orderby t.Name
                     select SqlModelConverters.ConvertBusinessObject(bo);
        return result.ToList();
    }
}

Я знаю, что Lazy-Evaluation будет гарантировать, что действительно отправлен только один запрос, но наличие этого временного объекта там на самом деле не так уж и хорошо.

11
задан Michael Stum 15 December 2010 в 20:21
поделиться