From 710b88e914933b3126bbe2122ce1d9a7d97bbf8e Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Sat, 4 Jun 2022 12:26:00 +0800 Subject: [PATCH] add ArrayToMany IncludeMany --- .../SelectProvider/Select1Provider.cs | 123 +++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs index 36cde5e9..04e2b711 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs @@ -670,10 +670,11 @@ namespace FreeSql.Internal.CommonProvider } //members.Clear(); 此行影响 ToChunk 第二次 + var isObservableCollection = collMem.Type == typeof(ObservableCollection); var listValueExp = Expression.Parameter(typeof(List), "listValue"); var setListValue = membersExpNotNull == null ? Expression.Lambda>>( - collMem.Type == typeof(ObservableCollection) ? + isObservableCollection ? (Expression)Expression.IfThen( Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List))), Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection).GetConstructor(new[] { typeof(List) }), listValueExp)) @@ -681,7 +682,7 @@ namespace FreeSql.Internal.CommonProvider Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.TypeAs(listValueExp, collMem.Type)) , t1parm, listValueExp).Compile() : Expression.Lambda>>(Expression.IfThen(membersExpNotNull, - collMem.Type == typeof(ObservableCollection) ? + isObservableCollection ? (Expression)Expression.IfThen( Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List))), Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection).GetConstructor(new[] { typeof(List) }), listValueExp)) @@ -1175,6 +1176,124 @@ namespace FreeSql.Internal.CommonProvider } break; case TableRefType.ArrayToMany: + if (true) + { + var subList = new List(); + var tbref2 = _commonUtils.GetTableByEntity(tbref.RefEntityType); + if (tbref.RefColumns[0] == tbref2.Primarys[0]) + { + var listKeys = list.Select(a => + { + var arrVal = getListValue(a, tbref.Columns[0].CsName, 0) as Array; + var arrObjVal = new object[arrVal.Length]; + arrVal.CopyTo(arrObjVal, 0); + return arrObjVal; + }).Where(a => a != null).ToArray(); + var arrExp = Expression.NewArrayInit(tbref.RefColumns[0].CsType, listKeys.SelectMany(a => a).Distinct() + .Select(a => Expression.Constant(Utils.GetDataReaderValue(tbref.RefColumns[0].CsType, a), tbref.RefColumns[0].CsType)).ToArray()); + var otmExpParm1 = Expression.Parameter(typeof(TNavigate), "a"); + var containsMethod = _dicTypeMethod.GetOrAdd(tbref.RefColumns[0].CsType, et => new ConcurrentDictionary()).GetOrAdd("Contains", mn => + typeof(Enumerable).GetMethods().Where(a => a.Name == mn).First()).MakeGenericMethod(tbref.RefColumns[0].CsType); + var refCol = Expression.MakeMemberAccess(otmExpParm1, tbref2.Properties[tbref.RefColumns[0].CsName]); + subSelect.Where(Expression.Lambda>( + Expression.Call(null, containsMethod, arrExp, refCol), otmExpParm1)); + + if (isAsync) + { +#if net40 +#else + if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken); + else subList = await subSelect.ToListAsync(selectExp, cancellationToken); +#endif + } + else + { + if (selectExp == null) subList = subSelect.ToList(true); + else subList = subSelect.ToList(selectExp); + } + + if (subList.Any() == false) + { + foreach (var item in list) + setListValue(item, new List()); + return; + } + var dicSubList = subList.ToDictionary(a => EntityUtilExtensions.GetEntityValueWithPropertyName(_orm, tbref.RefEntityType, a, tbref.RefColumns[0].CsName)?.ToString(), a => a); + + var parentNavs = new List(); + foreach (var navProp in tbref2.Properties) + { + if (tbref2.ColumnsByCs.ContainsKey(navProp.Key)) continue; + if (tbref2.ColumnsByCsIgnore.ContainsKey(navProp.Key)) continue; + var tr2ref = tbref2.GetTableRef(navProp.Key, false); + if (tr2ref == null) continue; + if (tr2ref.RefType != TableRefType.ManyToOne) continue; + if (tr2ref.RefEntityType != tb.Type) continue; + if (string.Join(",", tr2ref.Columns.Select(a => a.CsName).OrderBy(a => a)) != string.Join(",", tbref.RefColumns.Select(a => a.CsName).OrderBy(a => a))) continue; //- 修复 IncludeMany 只填充子属性中双向关系的 ManyToOne 对象值;防止把 ManyToOne 多个相同类型的导航属性值都填充了 + parentNavs.Add(navProp.Key); + } + for (var y = 0; y < list.Count; y++) + { + var item = list[y]; + var dicListKeys = listKeys[y]; + var navs = new List(); + foreach (var dlk in dicListKeys) + { + if (dlk == null) + { + navs.Add(null); + continue; + } + var dicListKey = dlk.ToString(); + dicSubList.TryGetValue(dicListKey, out var nav); + navs.Add(nav); + } + setListValue(item, navs); + } + dicSubList.Clear(); + subList.Clear(); + } + else if (tbref.Columns[0] == tb.Primarys[0]) + { + var listKeys = list.Select(a => getListValue(a, tbref.Columns[0].CsName, 0)).Distinct() + .Select(a => Utils.GetDataReaderValue(tbref.RefColumns[0].CsType.GetElementType(), a)).ToArray(); + var listKeysSql = _commonUtils.GetNoneParamaterSqlValue(subSelect._params, "arrtm", tbref.RefColumns[0], tbref.RefColumns[0].CsType, listKeys); + subSelect.Where($"{subSelectT1Alias}.{_commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)} && {listKeysSql}"); + + if (isAsync) + { +#if net40 +#else + if (selectExp == null) subList = await subSelect.ToListAsync(true, cancellationToken); + else subList = await subSelect.ToListAsync(selectExp, cancellationToken); +#endif + } + else + { + if (selectExp == null) subList = subSelect.ToList(true); + else subList = subSelect.ToList(selectExp); + } + + if (subList.Any() == false) + { + foreach (var item in list) + setListValue(item, new List()); + return; + } + var subListDic = subList.Select(a => { + var arrVal = EntityUtilExtensions.GetEntityValueWithPropertyName(_orm, tbref2.Type, a, tbref.RefColumns[0].CsName) as Array; + var arrObjVal = new object[arrVal.Length]; + arrVal.CopyTo(arrObjVal, 0); + return arrObjVal.Select(b => NativeTuple.Create(a, b?.ToString())); + }).SelectMany(a => a).GroupBy(a => a.Item2).ToDictionary(a => a.Key, a => a.Select(b => b.Item1).ToList()); + foreach (var item in list) + { + var itemKey = getListValue(item, tbref.Columns[0].CsName, 0)?.ToString(); + subListDic.TryGetValue(itemKey, out var navs); + setListValue(item, navs); + } + } + } break; } };