Код Linq для выбора одного элемента
Я нахожу, что пишу много кода, подобного этому, чтобы выбрать один элемент, который соответствует
var item = (from x in Items where x.Id == 123 select x).First();
Есть ли более чистый способ сделать это или это будет кратким, как я собираюсь получить?
РЕДАКТИРОВАТЬ: Должен сказать "Чистый способ с использованием синтаксиса linq". Я уже знал о синтаксисе лямбда, и он начинает выглядеть так, как будто это единственный способ. Я получил некоторую полезную информацию, хотя, спасибо всем, кто ответил.
Ответы
Ответ 1
Зависит от того, насколько вам нравится синтаксис запроса linq, вы можете использовать методы расширения напрямую:
var item = Items.First(i => i.Id == 123);
И если вы не хотите бросать ошибку, если список пуст, используйте FirstOrDefault
, который возвращает значение по умолчанию для типа элемента (null
для ссылочных типов):
var item = Items.FirstOrDefault(i => i.Id == 123);
if (item != null)
{
// found it
}
Single()
и SingleOrDefault()
также могут быть использованы, но если вы читаете из базы данных или что-то, что уже гарантирует уникальность, я бы не стал беспокоиться, поскольку он должен проверять список, чтобы увидеть, есть ли дубликаты и броски. First()
и FirstOrDefault()
останавливаются в первом совпадении, поэтому они более эффективны.
Из семейства First()
и Single()
, где они бросают:
-
First()
- бросает, если пуст/не найден, не бросает, если дубликат
-
FirstOrDefault()
- возвращает значение по умолчанию, если пусто/не найдено, не выбрасывает, если дубликат
-
Single()
- бросает, если пуст/не найден, бросает, если существует дубликат
-
SingleOrDefault()
- возвращает значение по умолчанию, если пусто/не найдено, выбрасывает, если существует дубликат
Ответ 2
FirstOrDefault или SingleOrDefault может быть в зависимости от вашего сценария, и хотите ли вы обрабатывать нулевое или большее совпадение:
FirstOrDefault: возвращает первый элемент последовательности или значение по умолчанию, если элемент не найден.
SingleOrDefault: возвращает единственный элемент последовательности или по умолчанию значение, если последовательность пуста; этот метод генерирует исключение, если в последовательности
имеется более одного элемента,
Я не знаю, как это работает в запросе linq 'from', но в синтаксисе лямбда выглядит так:
var item1 = Items.FirstOrDefault(x => x.Id == 123);
var item2 = Items.SingleOrDefault(x => x.Id == 123);
Ответ 3
Это предпочтительные методы:
var item = Items.SingleOrDefault(x => x.Id == 123);
или
var item = Items.Single(x => x.Id == 123);
Ответ 4
Это можно свести к минимуму.
var item = Items.First(x => x.Id == 123);
В настоящее время ваш запрос собирает все результаты (и может быть несколько) в пределах перечисляемого, а затем берет первый из этого набора, делая больше работы, чем необходимо.
Одиночные/SingleOrDefault заслуживают внимания, но только если вы хотите итерации по всей коллекции и убедитесь, что совпадение уникально в дополнение к выбору этого соответствия. First/FirstOrDefault просто займет первое совпадение и уйдет, независимо от того, сколько фактически существует дубликатов.
Ответ 5
Просто, чтобы облегчить кому-то жизнь, запрос linq с выражением лямбда
(from x in Items where x.Id == 123 select x).FirstOrDefault();
приводит к SQL-запросу с
select top (1)
.
Ответ 6
Вы можете использовать синтаксис метода расширения:
var item = Items.Select(x => x.Id == 123).FirstOrDefault();
Кроме того, я не уверен, насколько более кратким вы можете получить, не создавая собственных специализированных методов "First" и "FirstOrDefault".
Ответ 7
Я расскажу вам, что сработало для меня:
int id = int.Parse(insertItem.OwnerTableView.DataKeyValues[insertItem.ItemIndex]["id_usuario"].ToString());
var query = user.First(x => x.id_usuario == id);
tbUsername.Text = query.username;
tbEmail.Text = query.email;
tbPassword.Text = query.password;
Мой id - это строка, которую я хочу запросить, в этом случае я получил ее из radGrid, затем я использовал ее для запроса, но этот запрос возвращает строку, тогда вы можете назначить значения, полученные из запроса, в текстовое поле, или что-то еще, мне пришлось назначить их в текстовое поле.