Различия между LINQ to Objects и LINQ to SQL - PullRequest
5 голосов
/ 12 ноября 2009

Я уже некоторое время использую LINQ для запроса своих объектов POCO, но я еще не пробовал LINQ to SQL. Я предполагаю, что запросы LINQ to SQL каким-то образом преобразуются в эквивалентные запросы SQL, и, учитывая это, мне интересно, влияет ли это на то, как запросы LINQ to SQL или должны быть написаны.

Существуют ли существенные различия между LINQ to Objects и LINQ to SQL, которые влияют на то, как я должен написать запрос для любого из них?

Ответы [ 4 ]

3 голосов
/ 12 ноября 2009

Основное отличие состоит в том, что, как вы говорите, запросы LINQ to SQL преобразуются в SQL. Это означает, что есть код, который вы можете написать, который на самом деле не является конвертируемым или имеет слегка различную семантику - и вы узнаете это только во время выполнения.

Например:

var query = from person in people
            where person.Age == person.GetHashCode()
            select person;

будет хорошо скомпилироваться , но потерпит неудачу во время выполнения, потому что LINQ to SQL не знает, что делать с GetHashCode().

По сути, я нахожу, что LINQ to SQL гораздо сложнее предсказать, чем LINQ to Objects. Это не значит, что это бесполезно - это просто немного другой мир. MS проделала потрясающую работу, позволив вам писать запросы, которые очень часто просто делают то, что вы ожидаете, но не могут делать все.

2 голосов
/ 12 ноября 2009

LINQ to SQL будет использовать параметры сортировки сервера БД для столбцов для Where и OrderBy. LINQ to Objects будет использовать сравнения строк. Таким образом, первое может быть без учета регистра, а второе с учетом регистра. LINQ to Entities объединяет нули. Я предполагаю, что L2S делает то же самое, но я не проверял. Так что в L2E вы можете сделать:

let foo = item.Property.SomeNullableType

... и foo будут иметь значение NULL, если свойство равно NULL. Но в LINQ to Objects вы должны сделать что-то вроде:

let foo = item.Property != null ? item.Property.SomeNullableType : null

... или вы получите нулевое исключение.

1 голос
/ 12 ноября 2009

Одно отличие, с которым я сталкиваюсь, - это различия в группировке.

Когда вы группируете в linq по объектам, вы получаете результат иерархической формы (ключи, с дочерними объектами).

Когда вы группируете в SQL, вы получаете только ключи и агрегаты.

Когда вы группируете в linq to sql, если вы запрашиваете дочерние объекты (больше чем агрегаты), linq to sql будет повторно запрашивать каждую группу, используя ключ для получения этих дочерних объектов. Если у вас есть тысячи групп, это могут быть тысячи поездок туда и обратно.

  //this is ok
var results = db.Orders
  .GroupBy( o => o.CustomerID )
  .Select(g => new
  {
    CustomerId = g.Key,
    OrderCount = g.Count()
  });

//this could be a lot of round trips.
var results = db.Orders
  .GroupBy( o => o.CustomerID )
  .Select(g => new
  {
    CustomerId = g.Key,
    OrderIds = g.Select(o => o.OrderId)
  });

// this is ok
// used ToList to separate linqtosql work from linqtoObject work
var results = db.Orders
  .Select(o => new {o.CustomerId, o.OrderId})
  .ToList()
  .GroupBy(o => o.CustomerId)
  .Select(g => new
  {
    CustomerId = g.Key,
    OrderIds = g.Select(o => o.OrderId)
  });
1 голос
/ 12 ноября 2009

MSDN ссылка здесь и здесь должны помочь вам.

...