LINQ to Objects - Философия использования? - PullRequest
3 голосов
/ 24 марта 2009

Я начинаю изучать LINQ to Objects, но хочу знать, как дизайн приложения может лучше всего соответствовать LINQ to Objects.

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

По умолчанию приложение создает оператор SQL для извлечения только сотрудников-женщин из базы данных и помещает их в объект (список), который затем передается приложению для отображения и т. Д.

Чтобы получить наибольшее влияние от LINQ на объекты, я предполагаю, что сначала вам нужно будет получить все данные для сотрудников, а затем применить LINQ для фильтрации объекта и отображения только сотрудников женского пола. Преимущество состоит в том, что вы можете продолжать запрашивать сотрудников, не касаясь базы данных снова.

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

Что, если в таблице сотрудников есть 100 000 записей?

Я вижу преимущество LINQ .... но я уверен, что вам сначала нужно поместить ВСЕ данные в объект, из которого вы затем можете использовать LINQ для запроса.

Получение ВСЕХ данных может быть слишком дорогостоящим, чтобы делать его целесообразным, когда я могу просто снова запрашивать базу данных каждый раз, когда мне нужно другое подмножество данных.

Мысли

Ответы [ 6 ]

2 голосов
/ 24 марта 2009

Если для начала вам нужно только подмножество данных, извлекайте только это подмножество. Я не думаю, что имеет смысл получить все данные о сотрудниках в вашем примере.

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

Лично я считаю LINQ to Objects наиболее убедительным поставщиком LINQ. Легко предсказать, что он будет делать (потому что перевод не задействован), и это полезно на каждом уровне приложения. Мне ужасно не хватает, когда я пишу на Java - почти каждый раз, когда я делаю что-нибудь интересное с коллекцией, LINQ to Objects делает это проще.

1 голос
/ 24 марта 2009

LinqToObjects не предназначен для эффективной работы с 100 000 элементов в неиндексированной коллекции. Не является циклом foreach.

Философски, LinqToObjects и foreach работают в одном пространстве. Изучите циклы foreach в своем коде и посмотрите, написаны ли они более выразительно, как запросы LinqToObjects.

1 голос
/ 24 марта 2009

Философия использования? Вот общий ответ, который вы можете применить в другом месте.

Прочитайте несколько примеров, где инструмент полезен. Если вам не хватает причины использовать этот инструмент, потому что подобные примеры для вас никогда не возникают, забудьте об этом. Это может просто не быть применимо к вашему домену.

Если все данные, которыми вы манипулируете, находятся в СУБД, то, возможно, вам вообще не нужен Linq to Objects.

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

Пример: вы читаете файл, состоящий из строк простого текста.

var lines = File.ReadAllLines(fileName);

Как оказалось, lines теперь содержит массив строк, но массивы поддерживают IEnumerable, поэтому мы можем использовать методы Linq для них. Предположим, вы хотите удалить строки, в которых ничего нет:

var nonBlankLines = lines.Where(line => line.Trim() == string.Empty);

И предположим, что вы хотели, чтобы эти строки были в кавычках (наивная реализация - нужно экранировать существующие кавычки!):

var quoted = lines.Where(line => line.Trim() == string.Empty)
                  .Select(line => "\"" + line + "\"");

(Мне нравится выстраивать последовательные операции с точечным методом, выровненным друг под другом.)

И если я не собираюсь делать что-то еще со строками, я бы сделал это:

var quoted = File.ReadAllLines(fileName)
                 .Where(line => line.Trim() == string.Empty)
                 .Select(line => "\"" + line + "\"");

А затем предположим, что я хочу, чтобы все это было превращено в одну строку, разделенную запятыми, в строке есть метод с именем Join, который может это сделать, если сначала превратить все в массив:

var quoted = string.Join(", ", 
                         File.ReadAllLines(fileName)
                             .Where(line => line.Trim() == string.Empty)
                             .Select(line => "\"" + line + "\"")
                             .ToArray());

Или мы можем использовать способ Linqy:

var quoted = File.ReadAllLines(fileName)
                 .Where(line => line.Trim() == string.Empty)
                 .Select(line => "\"" + line + "\"")
                 .Aggregate((a, b) => a + ", " + b);

Также нет ничего сложного в заполнении нескольких пробелов, когда вы обнаружите, что для того, что вам нужно, нет существующего оператора (хотя иногда он уже есть). Один большой, который отсутствует, - это противоположность Aggregate, которую я назвал Util.Generate:

IEnumerable<T> Generate<T>(T item, Func<T, T> generator)
{
    for (; item != null; item = generator(item))
        yield return item;
}

Это очень удобно, когда у вас есть связанный список, который иногда появляется в объектных моделях. Примером является Exception.InnerException, который позволяет исключениям формировать связанный список с самым внутренним в конце. Предположим, мы хотим отобразить сообщение только из самого внутреннего исключения x:

MessageBox.Show(Util.Generate(x, i => i.InnerException).Last().Message);

Вспомогательный метод Generate преобразует связанный список в IEnumerable, позволяя другим методам Linq работать с ним. Ему просто нужно дать лямбду, чтобы сказать, как перейти к следующему элементу из текущего.

Может быть, это поможет вам начать, или, может быть, вам нужно больше примеров, или, может быть, вы буквально никогда не манипулируете данными, не полученными из СУРБД.

1 голос
/ 24 марта 2009

Вы можете использовать LINQ для гораздо большего, чем просто для запросов к базам данных. Подобно тому, как LINQ для объектов базы данных / XML / и т. Д. Выигрывает от отложенной обработки; и так же делают запросы к массивам, коллекциям, графам объектов и почти любой другой структуре памяти, о которой вы только можете подумать. Под отложенной обработкой я подразумеваю; Вы можете определить запрос (связанный с переменной), и он фактически не будет выполняться, пока вы не начнете перечислять результаты. Кроме того, логика предикатов для LINQ для любых объектов является цепочечной; думаю фильтрация конвейеров .

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

public static string RemovePunctuation(this string @string)
{
    if (string.IsNullOrEmpty(@string))
        return @string;

    var bytes = (
        from ch in @string
        where !Char.IsPunctuation(ch) && !Char.IsWhiteSpace(ch)
        select Convert.ToByte(ch)
        ).ToArray(); // <- calling to array enumerates the results

    return UnicodeEncoding.ASCII.GetString(bytes);
}

Конечно, есть и другие способы сделать то же самое, но это интересное использование LINQ против строки, и оно работает довольно хорошо.

1 голос
/ 24 марта 2009

Когда вы имеете дело с данными из базы данных, становится неясным, следует ли вам полагаться на LINQ-to-Objects или выполнять запросы в базе данных. Я думаю, в общем, если у вас есть база данных, всегда лучше делать как можно больше фильтрации и сортировки в БД и экономно использовать LINQ to Objects, особенно для больших коллекций данных.

Однако, поскольку код DAL может выглядеть неуклюже, я обнаружил, что иногда просто выполнить запрос FindAll в DAL, а затем просто использовать LINQ для объектов для сортировки и фильтрации. (Но только если ваша коллекция маленькая).

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

1 голос
/ 24 марта 2009

LINQ касается не только работы с базами данных.

Короче говоря, он предоставляет вам возможности запросов (с БД или без БД) к структуре (это могут быть строки, XML, список объектов и т. Д. В памяти). Таким образом, вам не нужно писать код, чтобы делать что-то вручную, и он более читабелен

Представьте себе, что нужно сравнить два списка и попытаться найти общие элементы среди них с помощью кода C #. Делать это с помощью SQL будет легко для понимания, но для того же самого в c # потребуется немного больше кода (и он не будет читаем, если вы не попытаетесь сделать это так)

LINQ дает синтаксический сахар, который создает впечатление, что вы пишете SQL для запросов / сортировки / агрегирования. SQL читается большинством разработчиков.

РЕДАКТИРОВАТЬ: Предположим, у вас есть подмножество данных, которые вы хотите показать пользователям. Теперь вам нужна какая-то операция фильтрации / агрегации / сортировки, чтобы вам не приходилось использовать БД для всего этого, как вы будете это делать?

Что если бы было что-то, что рассматривало бы мою коллекцию как некую запрашиваемую, сортируемую агрегированную структуру (аналогично таблице в SQL)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...