Получить различные записи, используя linq to entity - PullRequest
25 голосов
/ 22 августа 2010

Привет! Я использую linq to entity в моем приложении.Мне нужно получить отдельные записи, основанные на одном значении столбца «Имя»

Итак, у меня есть таблица, аналогичная приведенной ниже:

(User)
ID
Name
Country
DateCreated

Мне нужно выбрать все этопредметы но уникальны по Имени (уникальны).Можно ли выполнить с помощью linq, если да, пожалуйста, покажите мне, как.

var items = (from i in user select new  {i.id, i.name, i.country, i.datecreated}).Distinct();

Ответы [ 5 ]

27 голосов
/ 22 августа 2010

Метод Distinct() не работает должным образом, поскольку он не отправляет предикат DISTINCT SQL в базу данных. Используйте group вместо:

var distinctResult = from c in result
             group c by c.Id into uniqueIds
             select uniqueIds.FirstOrDefault();

Группа LINQ фактически создает подгруппы сущностей, для которых указывается указанное вами свойство:

Smith
  John
  Mary
  Ed
Jones
  Jerry
  Bob
  Sally

Синтаксис выше возвращает ключи, в результате чего получается отдельный список. Больше информации здесь:

http://imar.spaanjaars.com/546/using-grouping-instead-of-distinct-in-entity-framework-to-optimize-performance

8 голосов
/ 22 августа 2010

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

from i in user
group new {i.ID, i.Country, i.DateRecord} by i.Name into byNmGp
select byNmGp.First();

Редактировать: Entity Framework, конечно, очень популярный поставщик linq, ноздесь он не обрабатывает First(), хотя логически эквивалентный (в данном случае) FirstOrDefault() будет работать нормально.Я предпочитаю First(), когда его не принудительно вводят в FirstOrDefault() из-за ограничений EF, потому что его значение лучше соответствует искомому здесь.

Другой способ - определить вспомогательный класс:

private class MyRecord : IEquatable<MyRecord>
{
  public int ID;
  public string Name;
  public string Country;
  public DateTime DateCreated;
  public bool Equals(MyRecord other)
  {
    return Name.Equals(other.Name);
  }
  public override bool Equals(object obj)
  {
    return obj is MyRecord && Equals((MyRecord)obj);
  }
  public override int GetHashCode()
  {
    return Name.GetHashCode();
  }
}
/*...*/
var items = (from i in user select new MyRecord {i.ID, i.Name, i.Country, i.DateRecord}).Distinct();

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

2 голосов
/ 05 мая 2012

Вы можете использовать что-то вроде этого:

var distinctReports = reports.Select(c => c.CompanyCode)
                             .Distinct()
                             .Select(c => reports.FirstOrDefault(r => r.CompanyCode == c))
                             .ToList();
1 голос
/ 21 июля 2015

Вот еще один вариант, который я в итоге использовал, основанный на ответе Светланы.Показывает пример заполнения элемента управления GridView уникальными значениями.Спасибо!

        dataGridView_AnalyzeTestSuites.DataSource = (
            from tr in _db.TestResults
            where tr.TaskId == taskId
            select new { TestSuiteName = tr.Test.TestSuite.Name }
            ).Distinct().ToList();
1 голос
/ 22 августа 2010

Привет, вот как вы можете выбирать отдельные записи с помощью внутреннего соединения.Надеюсь, это поможет

var distinctrecords = 
(entity.Table.Join(entity.Table2, x => x.Column, y => y.Column, (x, y) => new {x, y})
             .Select(@t => new {@t.x.Column2, @t.y.Column3}))
             .GroupBy(t => t.Column2)
             .Select(g => g.FirstOrDefault());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...