我需要有关Linq自加入的帮助。

我有以下课程:

public class Owner
{
public string OwnerId {get;set;}
public string Name {get;set;}
public string Area {get;set;}
public string City {get;set;}
public string Sex {get;set;}
public List<Dog> dog {get;set;}
}


和桌子...

ID OwnerId OwnerName TypeId TypeName   TypeValue        TypeCodeId
1     1     John       1     Area      United States       440
2     1     John       2     City      Los-Angeles         221
3     1     John       3     Sex       Female              122
4     2     Mary       1     Area      Mexico              321
4     2     Mary       2     City      Cancun              345
............................................................


我需要以最快的方式将table1的结果解析为所有者列表。
注意:Type可以为null,但是我仍然需要显示所有者(因此,我认为左联接应该起作用)。

这是我的工作。 (所有者是一个包含table1结果的Web服务类)

public IEnumerable<Owner> GetOwners() {
  return  (from owner in owners
          join area in owners into owner_area
          from oa in owner_area.DefaultIfEmpty()
          join City in owners into owner_city
          from oc in owner_city.DefaultIfEmpty()
          join sex  in owners into owner_sex
          from os in owner_sex.DefaultIfEmpty()
          where oa.TypeId == 1 && oc.TypeId ==2 && os.TypeId ==3
          select new Owner() {OwnerId = owner.OwnerId,
                              Name = owner.Name,
                              Area = oa.TypeValue,
                              City = oc.TypeValue,
                              Sex = os.TypeValue}).Distinct();
}


该查询有几个问题:


它返回多个结果,但不一样不能按预期工作
我尝试使用GroupBy,但是它说不能将Owner隐式转换为IEnumerable <int, Owner>
超级慢


如何通过自我加入获得独特的记录并提高绩效?
谢谢

更新:
谢谢你们的测试,现在进行测试,但是我发现我忘了再提供一件事。我在表布局中添加了一个名为TypeCodeId的新列(请参见上文)
用户可以根据自己的选择过滤值。因此,我有用于区域,城市和性别的TypeCodeId + TypeValue字典。所有这些参数都是可选的(如果用户未选择任何参数,我只会向他们显示所有记录。

因此,假设用户选择了过滤器Area: Unites States和过滤器City: Los Angeles

他们我的查询看起来像这样:

Select Projects where Area equals United States(440) and City equals Los Angeles(221)


如果选择了Only Area:Mexico,那么我的查询将显示以下内容:

Select Projects where Area equals Mexico(321)


我不确定如何对示例中提供的内容执行可选的where子句。

最佳答案

为了获得最佳性能,请考虑采用这种方法。

public IEnumerable<Owner> GetOwners(IEnumerable<Tuple<int, int>> filter)
{
    var q = (from o in owners
            join f in filter on
               new {o.TypeId, o.TypeCodeId} equals
               new {TypeId = f.Item1, TypeCodeId = f.Item2}
            select o).ToList();

    var dic = q.ToDictionary (o => new {o.OwnerId, o.TypeId}, o => o.TypeValue);
    foreach (var o in q.Select(o => new { o.OwnerId, o.OwnerName }).Distinct())
    {
        var owner = new Owner()
        {
            OwnerId = o.OwnerId,
            Name = o.OwnerName
        };
        string lookup;
        if(dic.TryGetValue(new {o.OwnerId, TypeId = 1}, out lookup))
            owner.Area = lookup;
        if(dic.TryGetValue(new {o.OwnerId, TypeId = 2}, out lookup))
            owner.City = lookup;
        if(dic.TryGetValue(new {o.OwnerId, TypeId = 3}, out lookup))
            owner.Sex = lookup;

        yield return owner;
    }
}


为了获得更高的性能,您可以编写一个IEqualityComparer类,该类仅比较int OwnerId并将其发送到Distinct函数中

09-25 17:45
查看更多