简体   繁体   English

在LINQ中进行DISTINCT联接

[英]Make a DISTINCT join in LINQ

I have a GridView bound to an LinqToSql-Datasource. 我有一个绑定到LinqToSql-Datasource的GridView。

The Datasource represents 3 Tables which I select with a Join in Linq-Query. 数据源代表3个表,这些表是我在Linq-Query中用Join选择的。 The Tables are for persons, instititutions and memberships (mitgliedschaft). 该表适用于个人,机构和成员(mitgliedschaft)。

A Person could have various Memberships belonging to different institutions. 一个人可以具有属于不同机构的各种成员资格。

My Query gets all Memberships but in the Table are shown only informations of the person or the institution, so there are duplicated rows in the rable. 我的查询获得所有成员资格,但表中仅显示有关人员或机构的信息,因此该寓言中有重复的行。

I want only one person shown, although there are 3 memberships for example. 我只想显示一个人,尽管例如有3个成员。 In SQL I would do it with a left join o something else, but I am LINQ-Newbie. 在SQL中,我可以使用左连接或其他方式来实现,但是我是LINQ-Newbie。

My Query is: 我的查询是:

neonDataContext db = new neonDataContext();
                e.KeyExpression = "id";
                e.QueryableSource = from mitgliedschaft in db.mitgliedschaft

                                    join person in db.person on mitgliedschaft.person_id equals person.id
                                    join institution in db.institution on mitgliedschaft.verein_id equals institution.id

                                    select new
                                    {
                                        vorname = person.vorname,
                                        nachname = person.nachname,
                                        nameVerein = institution.name,
                                        vereinid = mitgliedschaft.verein_id,
                                        id = mitgliedschaft.id,
                                        verbandsnummer = person.verbandsMitgliedsNummer,
                                        strasse = person.strasse,
                                        plz = person.plz,
                                        ort = person.ort,
                                        geburtsdatum = person.geburtsdatum,
                                        geschlechtid = person.geschlechtid,
                                        statusid = mitgliedschaft.statusid,
                                        bezirk_id = mitgliedschaft.bezirk_id,
                                        kreis_id = mitgliedschaft.kreis_id,
                                        person_id = mitgliedschaft.person_id,
                                        deletedFlag = mitgliedschaft.deletedFlag
                                    };

Can someone tell me how to do distinct or left join with such a query, please? 有人可以告诉我如何对这种查询进行区分或左连接吗?

Since you are returning an enumeration of complex objects, the Distinct() operator by itself is inapplicable. 由于您要返回复杂对象的枚举,因此Distinct()运算符本身不适用。 Consider creating a class to represent the Person entity in your code and having it implement the IEquatable interface. 考虑创建一个类来表示代码中的Person实体,并使其实现IEquatable接口。 This will allow the runtime to decide when two Person objects are in fact identical, by your own custom comparison logic. 这将允许运行时通过您自己的自定义比较逻辑来确定两个Person对象实际上何时相同。

See this article for details: https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinct?view=netframework-4.8 有关详细信息,请参见本文: https : //docs.microsoft.com/zh-cn/dotnet/api/system.linq.enumerable.distinct?view=netframework-4.8

You can then use the Distinct() operator on the result set: 然后可以在结果集上使用Distinct()运算符:

neonDataContext db = new neonDataContext();
                e.KeyExpression = "id";
                e.QueryableSource = (from mitgliedschaft in db.mitgliedschaft

                                    join person in db.person on mitgliedschaft.person_id equals person.id
                                    join institution in db.institution on mitgliedschaft.verein_id equals institution.id

                                    select new Person()
                                    {
                                        vorname = person.vorname,
                                        nachname = person.nachname,
                                        nameVerein = institution.name,
                                        vereinid = mitgliedschaft.verein_id,
                                        id = mitgliedschaft.id,
                                        verbandsnummer = person.verbandsMitgliedsNummer,
                                        strasse = person.strasse,
                                        plz = person.plz,
                                        ort = person.ort,
                                        geburtsdatum = person.geburtsdatum,
                                        geschlechtid = person.geschlechtid,
                                        statusid = mitgliedschaft.statusid,
                                        bezirk_id = mitgliedschaft.bezirk_id,
                                        kreis_id = mitgliedschaft.kreis_id,
                                        person_id = mitgliedschaft.person_id,
                                        deletedFlag = mitgliedschaft.deletedFlag
                                    }).Distinct();

If you want to distinct by one field or multiple-field like person_id,you can add a extension function: 如果要通过一个字段或多个字段(例如person_id)进行区分,则可以添加扩展功能:

public static class  CustomDistinct{
        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            HashSet<TKey> seenKeys = new HashSet<TKey>();
            foreach (TSource element in source)
            {
                if (seenKeys.Add(keySelector(element)))
                {
                    yield return element;
                }
            }
        }
    }

Use it: 用它:

(from ... select...).DistinctBy(p => p.person_id); //one field

(from ... select...).DistinctBy(p => new{p.person_id,p.id}); //multiple-field

Tried several Ways to achieve the Goal (implementing distinct in different ways and implenenting distinctBy-Extension). 尝试了几种方法来实现目标(以不同的方式实施独特的方法,并以不同的方式通过扩展实现)。 The only Way that works in my case was, grouping and selecting first one: 在我的情况下,唯一有效的方法是分组并选择第一个:

neonDataContext db = new neonDataContext();
                e.KeyExpression = "id";
                e.QueryableSource = (from mitgliedschaft in db.mitgliedschaft

                                     join person in db.person on mitgliedschaft.person_id equals person.id
                                     join institution in db.institution on mitgliedschaft.verein_id equals institution.id

                                     select new
                                     {
                                         vorname = person.vorname,
                                         nachname = person.nachname,
                                         nameVerein = institution.name,
                                         vereinid = mitgliedschaft.verein_id,
                                         id = mitgliedschaft.id,
                                         verbandsMitgliedsNummer = person.verbandsMitgliedsNummer,
                                         strasse = person.strasse,
                                         plz = person.plz,
                                         ort = person.ort,
                                         geburtsdatum = person.geburtsdatum,
                                         geschlechtid = person.geschlechtid,
                                         statusid = mitgliedschaft.statusid,
                                         bezirk_id = mitgliedschaft.bezirk_id,
                                         kreis_id = mitgliedschaft.kreis_id,
                                         person_id = mitgliedschaft.person_id.Value,
                                         deletedFlag = mitgliedschaft.deletedFlag
                                     }).GroupBy(p => p.person_id).Select(p => p.First());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM