Получить отдельные записи, используя linq для сущности
Привет, я использую linq для объекта в своем приложении. Мне нужно получить разные записи на основе одного значения столбца "Имя"
Итак, у меня есть таблица, похожая на приведенную ниже:
(User)
ID
Name
Country
DateCreated
Мне нужно выбрать все эти элементы, но уникально на основе имени (уникально). Можно ли использовать linq, если да, пожалуйста, покажите мне, как это сделать.
var items = (from i in user select new {i.id, i.name, i.country, i.datecreated}).Distinct();
Ответы
Ответ 1
Метод 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
Ответ 2
Простым способом LINQ является группировка по имени, выбор отдельных групп по ключу, затем выбор на основе этого.
from i in user
group new {i.ID, i.Country, i.DateRecord} by i.Name into byNmGp
select byNmGp.First();
Edit: 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, делая то же самое или нет.
Ответ 3
Вы можете использовать что-то вроде этого:
var distinctReports = reports.Select(c => c.CompanyCode)
.Distinct()
.Select(c => reports.FirstOrDefault(r => r.CompanyCode == c))
.ToList();
Ответ 4
Привет, вот как вы можете выбрать отдельные записи с внутренним соединением. Надеюсь, что это поможет.
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());
Ответ 5
Вот еще один вариант, который я использовал, основываясь на ответе Светланы. Показывает пример заполнения элемента управления GridView уникальными значениями. Спасибо!
dataGridView_AnalyzeTestSuites.DataSource = (
from tr in _db.TestResults
where tr.TaskId == taskId
select new { TestSuiteName = tr.Test.TestSuite.Name }
).Distinct().ToList();