Зависит от LINQ

Хорошо, чем больше я использую LINQ, тем больше мне это нравится! Недавно я обнаружил, что работаю над некоторым устаревшим кодом. Это ваше классическое приложение DataSet и DataTable. Ну, добавив немного функциональности, я обнаружил, что действительно хочу просто запросить строки DataTable для результатов, которые я искал.

Позвольте мне повторить, что... вместо того, чтобы зацикливаться и добавлять в коллекцию temp, я просто хотел спросить коллекцию Rows, что мне нужно. Нет циклов, никаких временных переменных, просто дайте мне то, что я хочу.

var customerOrderIds = table.Rows.Cast<DataRow>()
   .Where(x => (string)x["CUSTOMER_ID"] == customerId)
   .Select(x => (string)x["CUSTOMER_ORDER_ID"])
   .Distinct();

Мой вопрос в том, хорошо ли это или нет, или увлекаюсь LINQ? Мне кажется, что этот декларативный стиль вытаскивания подмножества данных из коллекции хорошая вещь и более читаемая в конце. Но опять же, может быть, меня просто поразило:)

Ответ 1

Еще одно наблюдение; если вы не используете типизированные наборы данных, вы также можете узнать о методе расширения Field<>:

    var customerOrderIds = table.Rows.Cast<DataRow>()
       .Where(x => x.Field<string>("CUSTOMER_ID") == customerId)
       .Select(x => x.Field<string>("CUSTOMER_ORDER_ID"))
       .Distinct();

Или используя синтаксис запроса:

   var customerOrderIds = (
        from row in table.Rows.Cast<DataRow>()
        where row.Field<string>("CUSTOMER_ID") == customerId
        select row.Field<string>("CUSTOMER_ORDER_ID")
     ).Distinct();

Я не говорю, что это лучше или хуже - просто еще один жизнеспособный вариант.

(На самом деле, я не использую DataTable очень много, поэтому YMMV)

Ответ 2

Мне кажется хорошо, хотя я бы попытался использовать сильно типизированный набор данных, который делает запросы LINQ еще более приятными.

Но да, LINQ - очень хорошая вещь - и LINQ to Objects (и окружающие технологии для XML и DataSets) невероятно предсказуемы по сравнению с поставщиками LINQ из-за процесса. (Он менее сексуальный, чем LINQ to SQL, но более широко применимый IMO.)

Ответ 3

Запрос выглядит нормально.

Я хотел бы указать на две мелочи.

Нет циклов

System.Linq.Enumerable методы работают против контракта IEnumerable (T), который почти всегда означает looping-O (N) -решения. Два значения этого:

  • Предпочитает Any() over Count() > 0. Любой() есть O (1). Count() - O (N).
  • Присоединиться... все соединения - это вложенный цикл O (M * N).

.Cast

.Cast отлично работает для DataTable.Rows(все эти объекты - это строки, поэтому приведение всегда выполняется успешно). Для гетерогенных коллекций помните .OfType() - который отфильтровывает любые элементы, которые нельзя выполнить.

Наконец, имейте в виду, что запросы не выполняются до тех пор, пока они не будут перечислены! Вы можете принудительно перечислять foreach, ToList, ToArray, First, Single и многие другие.

Ответ 4

Лично, поскольку таблица данных не имеет возможности самостоятельно выполнять выделение, я скажу, что это не так уж плохо.

Я мог бы спросить, хотя бы какой-то способ в конечном итоге перейти к использованию объектов, а не таблиц данных, так как я думаю, что будущим разработчикам будет легче понять.

Ответ 5

Ты не увлекаешься вообще. Есть фактические работы, опубликованные в LINQ to DataSets. Наличие таких четких, декларативных запросов объектов позволяет значительно упростить работу кода. Но вы должны помнить, что в то время, когда вы фильтруете данные, все это уже было отброшено. Вы можете захотеть добавить фильтрацию в SQL для запроса DataSet.

Ответ 6

LINQ просто записывает для вас код "looping/temp variable". LINQ помогает быстрее писать код (и более читаемым).

Вы хороший код.

Ответ 7

Соединение (используя ключевое слово join, но не ключевое слово from) использует словарь для совпадений и, таким образом, O(M+N).

Итак, это группа, но не следующее:

from x in Xs
from y in Ys
    .Where(o => o == x)
select new
{
    x,
    y
}

который равен O(M*N).