Linq到实体多对多的左连接树

时间:2015-01-22 09:59:38

标签: c# entity-framework linq-to-entities

我正在注意EF6 Code First,我有5个表/实体,具有多对多关系,如下所示:

[Table("TableA")]
public class TableA {
  public Guid Id { get; set; }
  public string PropA { get; set; }
}

[Table("TableB")]
public class TableB {
  public Guid Id { get; set; }
  public string PropB { get; set; }
}

[Table("TableC")]
public class TableC {
  public Guid Id { get; set; }
  public string PropC { get; set; }
}

[Table("TableAB")]
public class TableAB {
  [ForeignKey("TableA")]
  public Guid TableAId { get; set; }
  public TableA { get; set; }
  [ForeignKey("TableB")]
  public Guid TableBId { get; set; }
  public TableB { get; set; }
}

[Table("TableBC")]
public class TableBC {
  [ForeignKey("TableB")]
  public Guid TableBId { get; set; }
  public TableB { get; set; }
  [ForeignKey("TableC")]
  public Guid TableCId { get; set; }
  public TableC { get; set; }
}

我正在寻找使用linq实体并获得一个“树”对象,如下所示,而不使用导航:

new List<A_DTO>() {
  Id: ...
  PropA: ...
  B: new List<B_DTO>(){
    Id: ...
    PropB: ...
    C: new List<C_DTO>(){
       Id: ...
       PropC: ...
    }
  }
}

我遇到的另一个问题是在某些情况下A和B或B和C之间不存在记录,这就是我使用左连接的原因。 我尝试了什么,它看起来非常混乱,不确定它是否按预期工作:

from a in Repository.All<TableA>()
join abT in Repository.All<TableAB>() on a.Id equals abT.TableAId into abTemp
from ab in abTemp.DefaultIfEmpty()
join bT in Repository.All<TableB>() on ab.TableBId equals bT.Id into bTemp
from b in bTemp.DefaultIfEmpty()
join abT in Repository.All<TableBC>() on b.Id equals bcT.TableBId into bcTemp
from bc in bcTemp.DefaultIfEmpty()
join cT in Repository.All<TableC>() on bc.TableCId equals cT.Id into cTemp
from c in bTemp.DefaultIfEmpty()
select new A_DTO(){
   Id: a.Id,
   PropA: a.PropA,
   B: abTemp.Select(_ab => new B_DTO(){
      Id: _ab.B.Id, // what if _ab.B is null?
      PropB: _ab.B.PropB,
      C: bcTemp.Select(_bc => new C_DTO(){
         Id: _bc.C.Id, // what if _bc.C is null?
         PropC: _bc.C.PropC
      }
   }
}

有没有办法以更简单/愉快的方式做到这一点?

谢谢!

1 个答案:

答案 0 :(得分:0)

我认为这应该有效(这告诉EF不要对B和B.C使用延迟加载,因此包括对象):

Repository.All()<TableA>().Include(x => x.B).Include(x => x.B.C)

默认情况下,所有相关对象都是虚拟属性,并视为延迟加载。您不需要对对象的属性执行此操作,因此只需包含B属性即可包含a.propa和a.b.propa。