2

在 sql 我有一个像这样的表:

PersonOrganisationRole

其中有以下列:

PersonId, OrganisationId RoleId

所以这是一个人、组织和角色之间的三向表。

所以我想创建一种方法来获取一个人所属的所有组织:

public class Person
{
  public IEnumerable<Organisation> Organisations
        {
            get 
            { 
                var organisations = new List<Organisation>();

                foreach (var personOrganisationRole in PersonOrganisationRoles.Where(personOrganisationRole => !organisations.Contains(personOrganisationRole.Organisation)))
                {
                    organisations.Add(personOrganisationRoles.Organisation);
                }

                return organisations;
            }
        }
}

所以我基本上是通过遍历表中的所有项目来填充一个列表,并且如果我还没有添加它,则只添加它。这很重要,因为表中可能有多个行具有相同的 PersonId 和 OrganisationId,因为一个人在一个组织中可能有多个角色。

我在想,虽然必须有更好的方法来编写这段代码。

有什么建议么?

4

4 回答 4

2

You can use LINQ's Distinct operator to do this unique-collecting, and ToList to collect the results in a list:

return PersonOrganisationRoles
    .Distinct(x => x.Organisation)
    .ToList();
于 2012-10-14T20:22:45.943 回答
1
public IEnumerable<Organisation> Organisations
{
    get 
    { 
        return PersonOrganisationRoles
            .Select(por => por.Organisation)
            .Distinct()
            .ToList();
    }
}

您将要检查组织实施

  • GetHashcodeEquals正确地
  • 可选地实现IEquatable<Organisation>

Distinct uses these to establish whether the item is already in the collection. (Contains did the same in the original sample, so that's probably what you intended)

于 2012-10-14T20:19:44.810 回答
0

Make it a function rather than property.

We are used to write objectInstance.PropertyName and usually think that this is fast operation that accesses some piece of data that is already in memory. In your case any call to Person.Organizations involves some processing and maybe even IO operations.

The other, possibly more important, point is that when I do:

var a = myPerson.Organizations;
var b = myPerson.Organizations;

I expect that a is pointing to the same List<> instance in memory as b.

And in your code that is not true. So please change the property to function or cache the result in private property so that processing is done only once. Like this:

public class Person
{
  private IEnumerable<Organisation> organizations; 

  public IEnumerable<Organisation> Organisations
  {
    get 
    { 
       if (organizations != null) return organizations;

       organisations = new List<Organisation>();
       // fill list here 
       return organisations;
     }
  }
}
于 2012-10-14T20:30:27.073 回答
0

A combination of the Linq Select() and Distinct() methods should do it.

 var organisations = PersonOrganisationRoles
              .Select<PersonOrganisationRoles,Organisation>(p => p.Organisation )
              .Distinct();
于 2012-10-14T20:48:06.603 回答