Есть ли способ использовать Distinct в синтаксисе запроса LINQ?

#c# #linq

#c# #linq

Вопрос:

Есть ли способ переписать:

 var tbl = ds.TABLES;
var q = from c in tbl
        select c.TABLE_TYPE;
string s = "";
foreach (var item in q.Distinct())
{
    s  = "["   item   "]";
}        
MessageBox.Show(s);
  

Чтобы вызов Distinct() выполнялся в запросе LINQ?

Ответ №1:

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

 var q = (from c in tbl
         select c.TABLE_TYPE).Distinct();
  

Комментарии:

1. дополнительная информация; приведенный выше запрос создаст следующий sql select distinct c.TABLE_TYPE from tbl c при использовании против sql, поэтому не беспокойтесь о проблемах с производительностью.

Ответ №2:

Distinct Метод расширения в LINQ не имеет эквивалента синтаксиса запроса.

Смотрите https://learn.microsoft.com/en-us/archive/blogs/charlie/linq-farm-using-distinct-and-avoiding-lambdas для получения дополнительной информации о том, почему.

Комментарии:

1. Ссылка теперь недоступна — вы знаете, где я могу найти post? Мне было бы интересно понять, почему это так.

2. @EJoshuaS-ReinstateMonica вот ссылка на архив статьи 🙂 web.archive.org/web/20160216044315/http://blogs.msdn.com:80/b /…

Ответ №3:

 (from c in tbl select c.TABLE_TYPE).Distinct();
  

Комментарии:

1. Я предполагаю, что OP, который хотел заменить var item in q.Distinct() синтаксисом запроса, уже знал об этом. Удивительно, что сообщение, которое не отвечает на вопрос, может набрать 14 голосов!

Ответ №4:

VB обладает этой функциональностью, если вы размещаете distinct после select .

Ответ №5:

Вы можете захватить HashSet и поместить предложение where перед select:

 var hs = new HashSet<char>();

from c in "abcabcd"
where hs.Add(c)
select c;
  

Комментарии:

1. Умно. Увы, существует необходимость заранее объявить HashSet, что снижает качество самодостаточности выражения запроса.

Ответ №6:

При поиске Distinct-функции для LINQ, обнаружив этот вопрос и поняв, что его не существует, мой обходной путь заключается в использовании GroupBy(). Очевидная проблема заключается в том, что набор distinct не содержит всех данных (допустим, у вас есть три поля, но вы хотите различать только два поля, в которых отсутствует значение для последнего поля, но, опять же, DISTINCT в t-sql работает таким же образом).

LINQ-code (отсюда и дамп):

 void Main()
{
    var gt = new GenerateThings();
    var dlist = gt.list();
    dlist.Dump();

    dlist.GroupBy(x => new {x.id, x.cat}).Dump();
}

public class model
{
    public int id {get;set;}
    public int cat {get;set;}
    public int type {get;set;}
}

public class GenerateThings
{
    public List<model>list()
    {
        var dlist = new List<model>();
        dlist.Add(createNew(1, 1, 1));
        dlist.Add(createNew(1, 1, 1));
        dlist.Add(createNew(1, 2, 1));
        dlist.Add(createNew(1, 2, 1));
        dlist.Add(createNew(1, 1, 2));
        dlist.Add(createNew(1, 1, 2));
        dlist.Add(createNew(1, 1, 2));
        return dlist;
    }
    private model createNew(int id, int cat, int type){
        return new model{
            id = id,
            cat = cat,
            type = type
        };
    }
}
  

LINQ-результат дампа