我有一个像这样的表:
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,因为一个人可以在组织中拥有多个角色。
我想虽然必须有更好的方法来编写这段代码。
有什么建议吗?
答案 0 :(得分:2)
您可以使用LINQ的Distinct
运算符执行此唯一收集,并使用ToList
将结果收集到列表中:
return PersonOrganisationRoles
.Distinct(x => x.Organisation)
.ToList();
答案 1 :(得分:1)
public IEnumerable<Organisation> Organisations
{
get
{
return PersonOrganisationRoles
.Select(por => por.Organisation)
.Distinct()
.ToList();
}
}
您需要检查该组织是否已实施
GetHashcode
和Equals
正确IEquatable<Organisation>
Distinct使用这些来确定该项目是否已在集合中。 (Contains
在原始样本中做了同样的事情,所以这可能就是你想要的那样)
答案 2 :(得分:0)
使它成为一种功能,而不是财产。
我们习惯于编写objectInstance.PropertyName,并且通常认为这是访问已经在内存中的某些数据的快速操作。在您的情况下,对Person.Organizations的任何调用都涉及一些处理,甚至可能是IO操作。
另一个可能更重要的一点是,当我这样做时:
var a = myPerson.Organizations;
var b = myPerson.Organizations;
我希望a指向同一个List&lt;&gt;内存中的实例为b。
在您的代码中并非如此。因此,请更改属性以运行或将结果缓存在私有属性中,以便只进行一次处理。像这样:
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;
}
}
}
答案 3 :(得分:0)
Linq Select()和Distinct()方法的组合应该这样做。
var organisations = PersonOrganisationRoles
.Select<PersonOrganisationRoles,Organisation>(p => p.Organisation )
.Distinct();