我需要帮助了解如何在Linq-to-Entities语句中执行多个连接。我总是很难理解Linq连接的表达式,特别是多连接。我总是最终使用子查询。例如:
public List<MyReportItem> GetReportItemsHelper(string[] years, string[] quarters, string[] areas, string myType, string[] ownerships, IEnumerable<String> fieldCodes)
{
var _reportItems = _db.MytableEntity1
.Where(c => c.FieldID.Equals(MY_ID) //Id Field
&& years.Contains(c.PeriodYear) //PeriodYear/Year
&& quarters.Contains(c.Period) //Period/Quarters
&& c.MyType.Equals(myType) //Special Type
&& areas.Contains(c.Area) //Area
&& ownerships.Contains(c.Ownership)) //Ownership
.Where(c => fieldCodes.Contains(c.FieldCode)) //Field Code
.Where(c => c.Suppress.Equals("0")) //Suppression is false
.Select(c => new MyReportItem
{
Field1 = c.FieldA,
Field2 = c.FieldB,
Field3 = c.FieldC.TrimEnd(),
//Sub-queries
Field4 = _db.MytableEntity2.Where(g => g.FieldID.Equals(c.FieldID) && g.MyType.Equals(c.MyType) && g.Area.Equals(c.Area)).Select(g => g.AreaName.TrimEnd()).FirstOrDefault(),
Field5 = _db.MytableEntity3.Where(o => o.Ownership.Equals(c.Ownership)).Select(o => o.OwnerTitle.TrimEnd()).FirstOrDefault(),
Field6 = _db.MytableEntity4.Where(i => c.FieldCode.Equals(i.FieldCode) && myType.Equals(c.MyType)).Select(i => i.FieldTitle).FirstOrDefault(),
Field7 = _db.MytableEntity4.Where(i => c.FieldCode.Equals(i.FieldCode) && myType.Equals(c.MyType)).Select(i => i.FieldLevel).FirstOrDefault(),
Field8 = c.FieldD,
Field9 = c.FieldE,
Field10 = c.FieldF,
Field11 = c.FieldG,
Field12 = c.FieldH,
Field13 = c.FieldI,
Field14 = c.FieldJ,
Field15 = c.FieldK
}).Distinct().ToList();
return _reportItems; //return report detail items
}
但是现在我面临着一个非常庞大的数据库(可能有6000万条或更多的记录?),而且子查询会阻碍我们的响应时间。我想解决这个问题,并利用“联接”。我看到很多示例显示如何执行联接,但我几乎看不到任何带有多个联接的示例。
如何在'MytableEntity2','MytableEntity3','MytableEntity4'上执行多个连接(在新的'MyReportItem'中),以消除4-7字段的子查询?如何将4个实体表组合成一个表达式?谢谢!
答案 0 :(得分:1)
您可以使用GroupJoin
执行与FirstOrDefault
的子查询相同的操作。请注意,如果您知道每个子查询都会产生1个匹配,则可以使用Join
而不使用FirstOrDefault
。
var rpt = MytableEntity1
.Where(c => c.FieldID.Equals(MY_ID) //Id Field
&& years.Contains(c.PeriodYear) //PeriodYear/Year
&& quarters.Contains(c.Period) //Period/Quarters
&& c.MyType.Equals(myType) //Special Type
&& areas.Contains(c.Area) //Area
&& ownerships.Contains(c.Ownership)) //Ownership
.Where(c => fieldCodes.Contains(c.FieldCode)) //Field Code
.Where(c => c.Suppress.Equals("0")) //Suppression is false
.GroupJoin(MytableEntity2, c => new { c.FieldID, c.MyType, c.Area }, g => new { g.FieldID, g.MyType, g.Area }, (c, gj) => new { c, g = gj.Select(g => g.AreaName.TrimEnd()).FirstOrDefault() })
.GroupJoin(MytableEntity3, cg => cg.c.Ownership, o => o.Ownership, (cg, oj) => new { cg.c, cg.g, o = oj.Select(o => o.OwnerTitle.TrimEnd()).FirstOrDefault() })
.GroupJoin(MytableEntity4, cgo => cgo.c.FieldCode, i => i.FieldCode, (cgo, ij) => new { cgo.c, cgo.g, cgo.o, i = ij.FirstOrDefault() })
.Select(cgoi => new MyReportItem {
Field1 = cgoi.c.FieldA,
Field2 = cgoi.c.FieldB,
Field3 = cgoi.c.FieldC.TrimEnd(),
Field4 = cgoi.g,
Field5 = cgoi.o,
Field6 = cgoi.i.FieldTitle,
Field7 = cgoi.i.FieldLevel,
Field8 = cgoi.c.FieldD,
Field9 = cgoi.c.FieldE,
Field10 = cgoi.c.FieldF,
Field11 = cgoi.c.FieldG,
Field12 = cgoi.c.FieldH,
Field13 = cgoi.c.FieldI,
Field14 = cgoi.c.FieldJ,
Field15 = cgoi.c.FieldK
}).Distinct().ToList();