2008-10-02 3 views
5

Я встречаюсь с некоторыми особенностями с 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, он также отлично работает, пока не будет нулевых значений.

Любые идеи?

Энтони

+0

Кажется, у вас есть два совершенно разных запросов. Один выбирает из MyItems в объекте MyList. Второй - выбор из объектов MyList (а не MyItems). Являются ли типы данных одинаковыми для обоих? Это довольно сложно отладить, не зная, что такое структуры таблицы. – Bryant 2008-10-02 16:06:48

ответ

14

Я бы сделать 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() : "" 
} 
+0

Ooooh Мне понравилось, что .AsEnumerable() раскололся там. Ницца. – Lucas 2008-10-07 22:54:20

8

В первом запросе, вы уже получили данные обратно из базы данных по времени вторая линия проходит (вар элементы = ...). Это означает, что вторая строка выполняется на клиенте, где ToShortDateString может работать довольно счастливо.

Во втором запросе, поскольку выбор выполняется непосредственно в коллекции IQueryable (dataContext.MyLists), он пытается перевести выбор в SQL для обработки на сервере, где ToShortDateString не понят - следовательно, «Не удалось Перевести .. "исключение.

Чтобы понять это немного лучше, вам действительно нужно понять разницу между IQueryable и IEnumerable, и в этот момент запрос Linq To Sql перестает быть IQueryable и становится IEnumerable. Об этом в Интернете много.

Надеется, что это помогает,

Пол

6

Так как сообщение об ошибке говорит вам, что разница заключается в том, что можно сделать локально стихи удаленно при подключении к SQL.

Код Linq должен быть преобразован Linq в SQL в команду SQL для удаленных удалений данных - все, что должно быть сделано локально, не может быть включено.

Как только вы вытащили его в локальный объект (в первом примере), он больше не использует Linq to SQL, а просто Linq. В этот момент вы можете делать локальные манипуляции.

2

Возможно, у вас была ошибка копирования и вставки или просто опечатка в вашем примере. Но если нет, это может быть проблемой ...

Во втором запросе вы запрашиваете коллекцию списков, тогда как в первом запросе вы запрашивали элементы в списке. Но вы не настроили запрос на учет этой разницы.

Возможно, вам это понадобится. Обратите внимание на прокомментированные строки, которые не отображаются во втором примере.

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() : "" 
         };