Особенности LINQ to SQL
Я встречаюсь с некоторыми особенностями LINQ to SQL.
С относительно простым запросом я хочу выбрать некоторые поля, но поля даты будут отформатированы как строки, которые я впервые получил следующим образом:
var list = dataContext.MyLists.Single(x => x.ID == myId);
var items = from i in list.MyItems
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
Позже я попробовал следующий запрос, который точно такой же, за исключением того, что я запрашиваю прямо из моего dataContext, а не элемент в моем первом запросе:
var items = from i in dataContext.MyLists
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
Первый работает отлично, но второй запрос дает:
Невозможно перевести выражение "..." в SQL и не может рассматривать его как локальное выражение.
Если я удалю строки, которые форматируют дату, она отлично работает. Если я удалю проверку .HasValue, он также будет работать нормально, пока не будет нулевых значений.
Любые идеи?
Энтони
Ответы
Ответ 1
Я бы сделал часть SQL без форматирования, а затем сделаю форматирование на стороне клиента:
var items = list.MyItems.Select(item => new { item.ID, item.Sector, item.Description,
item.CompleteDate, item.DueDate })
.AsEnumerable() // Don't do the next bit in the DB
.Select(item => new { item.ID, item.Sector, item.Description,
CompleteDate = FormatDate(CompleteDate),
DueDate = FormatDate(DueDate) });
static string FormatDate(DateTime? date)
{
return date.HasValue ? date.Value.ToShortDateString() : ""
}
Ответ 2
В первом запросе вы уже получили данные из базы данных к моменту выполнения второй строки (var items =...). Это означает, что вторая строка выполняется на клиенте, где ToShortDateString может работать довольно счастливо.
Во втором запросе, поскольку выбор выполняется непосредственно в коллекции IQueryable (dataContext.MyLists), он пытается перевести выбор в SQL для обработки на сервере, где ToShortDateString не понят - следовательно, "Не удалось перевести".. "исключение.
Чтобы понять это немного лучше, вам действительно нужно понять разницу между IQueryable и IEnumerable, и в этот момент запрос Linq To Sql перестает быть IQueryable и становится IEnumerable. В Интернете есть много материала.
Надеюсь, что это поможет,
Пол
Ответ 3
Как и сообщение об ошибке, различие связано с тем, что можно удаленно удалять локальными стилями при подключении к SQL.
Код Linq должен быть преобразован Linq в SQL в команду SQL для удаленных данных - все, что нужно сделать локально, не может быть включено.
Как только вы поместили его в локальный объект (в первом примере), он больше не использует Linq to SQL, а просто Linq. В этот момент вы можете делать локальные манипуляции на нем.
Ответ 4
Возможно, в вашем примере была ошибка копирования и вставки или просто опечатка. Но если нет, это может быть проблемой...
Во втором запросе вы запрашиваете коллекцию списков, тогда как в первом запросе вы запрашивали элементы в списке. Но вы не скорректировали запрос для учета этой разницы.
Вам может понадобиться. Обратите внимание на прокомментированные строки, которые не отображаются во втором примере.
var items = from aList in dataContext.MyLists
from i in aList.MyItems // Access the items in a list
where aList.ID == myId // Use only the single desired list
select
new
{
i.ID,
i.Sector,
i.Description,
CompleteDate = i.CompleteDate.HasValue ? i.CompleteDate.Value.ToShortDateString() : "",
DueDate = i.DueDate.HasValue ? i.DueDate.Value.ToShortDateString() : ""
};
Ответ 5
ToShortDateString()
не поддерживается Linq to SQL http://msdn.microsoft.com/en-us/library/bb882657.aspx