From d617b237de5181a8c63910a5ca836f63236ad1de Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Tue, 29 Sep 2020 11:31:57 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E8=A1=A5=E5=85=85=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E6=96=B9=E6=B3=95=20ToListAsync(a=20=3D>=20{})=20=E5=AF=B9=20I?= =?UTF-8?q?ncludeMany=20=E7=9A=84=E6=94=AF=E6=8C=81=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SelectProvider/Select1Provider.cs | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 387a0993..a940c2f7 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -195,7 +195,7 @@ namespace FreeSql.Internal.CommonProvider _tables[0].Parameter = select.Parameters[0]; if (_includeToList?.Any() != true) return this.InternalToList(select.Body); - var findIncludeMany = new List(); + var findIncludeMany = new List(); //支持指定已经使用 IncudeMany 的导航属性 var map = new ReadAnonymousTypeInfo(); var field = new StringBuilder(); var index = 0; @@ -1167,11 +1167,72 @@ namespace FreeSql.Internal.CommonProvider _tables[0].Parameter = column.Parameters[0]; return this.InternalSumAsync(column?.Body); } - public Task> ToListAsync(Expression> select) + async public Task> ToListAsync(Expression> select) { - if (select == null) return this.InternalToListAsync(select?.Body); + if (select == null) return await this.InternalToListAsync(select?.Body); _tables[0].Parameter = select.Parameters[0]; - return this.InternalToListAsync(select?.Body); + if (_includeToList?.Any() != true) return await this.InternalToListAsync(select.Body); + + var findIncludeMany = new List(); //支持指定已经使用 IncudeMany 的导航属性 + var map = new ReadAnonymousTypeInfo(); + var field = new StringBuilder(); + var index = 0; + _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select.Body, this, null, _whereCascadeExpression, findIncludeMany, true); + var af = new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null); + if (findIncludeMany.Any() == false) return await this.ToListMapReaderPrivateAsync(af, null); + + var parmExp = Expression.Parameter(_tables[0].Table.Type, _tables[0].Alias); + var incNewInit = new IncludeManyNewInit(_tables[0].Table, parmExp); + foreach (var inc in _includeInfo) + { + var curIncNewInit = incNewInit; + Expression curParmExp = parmExp; + for (var a = 0; a < inc.Value.Length - 1; a++) + { + curParmExp = Expression.MakeMemberAccess(parmExp, inc.Value[a].Member); + if (curIncNewInit.Childs.ContainsKey(inc.Value[a].Member.Name) == false) + curIncNewInit.Childs.Add(inc.Value[a].Member.Name, curIncNewInit = new IncludeManyNewInit(_orm.CodeFirst.GetTableByEntity(inc.Value[a].Type), curParmExp)); + else + curIncNewInit = curIncNewInit.Childs[inc.Value[a].Member.Name]; + } + curIncNewInit.IsOutputPrimary = true; + } + MemberInitExpression GetIncludeManyNewInitExpression(IncludeManyNewInit imni) + { + var bindings = new List(); + if (imni.IsOutputPrimary) bindings.AddRange(imni.Table.Primarys.Select(a => Expression.Bind(imni.Table.Properties[a.CsName], Expression.MakeMemberAccess(imni.CurrentExpression, imni.Table.Properties[a.CsName])))); + if (imni.Childs.Any()) bindings.AddRange(imni.Childs.Select(a => Expression.Bind(imni.Table.Properties[a.Key], GetIncludeManyNewInitExpression(a.Value)))); + return Expression.MemberInit(imni.Table.Type.InternalNewExpression(), bindings); + } + + var otherNewInit = GetIncludeManyNewInitExpression(incNewInit); //获取 IncludeMany 包含的最简化字段 + if (otherNewInit.Bindings.Any() == false) return await this.ToListMapReaderPrivateAsync(af, null); + + var otherMap = new ReadAnonymousTypeInfo(); + field.Clear(); + _commonExpression.ReadAnonymousField(_tables, field, otherMap, ref index, otherNewInit, this, null, _whereCascadeExpression, null, true); + var otherRet = new List(); + var otherAf = new ReadAnonymousTypeOtherInfo(field.ToString(), otherMap, otherRet); + + af.fillIncludeMany = new List>(); + var ret = await this.ToListMapReaderPrivateAsync(af, new[] { otherAf }); + await this.SetListAsync(otherRet.Select(a => (T1)a).ToList()); //级联加载 + + foreach (var fim in af.fillIncludeMany) + { + var splitKeys = fim.Item1.Split('.'); + var otherRetItem = otherRet[fim.Item3]; + var otherRetItemType = _tables[0].Table.Type; + foreach (var splitKey in splitKeys) + { + otherRetItem = _orm.GetEntityValueWithPropertyName(otherRetItemType, otherRetItem, splitKey); + otherRetItemType = _orm.CodeFirst.GetTableByEntity(otherRetItemType).Properties[splitKey].PropertyType; + } + if (otherRetItem == null) continue; + var otherList = otherRetItem as IEnumerable; + foreach (var otherListItem in otherList) fim.Item2.Add(otherListItem); + } + return ret; } public Task> ToListAsync() => ToListAsync(GetToListDtoSelector());