add ArrayToMany IncludeMany

This commit is contained in:
2881099 2022-06-04 12:26:00 +08:00
parent 8248057d5c
commit 710b88e914

View File

@ -670,10 +670,11 @@ namespace FreeSql.Internal.CommonProvider
} }
//members.Clear(); 此行影响 ToChunk 第二次 //members.Clear(); 此行影响 ToChunk 第二次
var isObservableCollection = collMem.Type == typeof(ObservableCollection<TNavigate>);
var listValueExp = Expression.Parameter(typeof(List<TNavigate>), "listValue"); var listValueExp = Expression.Parameter(typeof(List<TNavigate>), "listValue");
var setListValue = membersExpNotNull == null ? var setListValue = membersExpNotNull == null ?
Expression.Lambda<Action<T1, List<TNavigate>>>( Expression.Lambda<Action<T1, List<TNavigate>>>(
collMem.Type == typeof(ObservableCollection<TNavigate>) ? isObservableCollection ?
(Expression)Expression.IfThen( (Expression)Expression.IfThen(
Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))), Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))),
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp)) Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp))
@ -681,7 +682,7 @@ namespace FreeSql.Internal.CommonProvider
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.TypeAs(listValueExp, collMem.Type)) Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.TypeAs(listValueExp, collMem.Type))
, t1parm, listValueExp).Compile() : , t1parm, listValueExp).Compile() :
Expression.Lambda<Action<T1, List<TNavigate>>>(Expression.IfThen(membersExpNotNull, Expression.Lambda<Action<T1, List<TNavigate>>>(Expression.IfThen(membersExpNotNull,
collMem.Type == typeof(ObservableCollection<TNavigate>) ? isObservableCollection ?
(Expression)Expression.IfThen( (Expression)Expression.IfThen(
Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))), Expression.NotEqual(listValueExp, Expression.Constant(null, typeof(List<TNavigate>))),
Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp)) Expression.Assign(Expression.MakeMemberAccess(membersExp, collMem.Member), Expression.New(typeof(ObservableCollection<TNavigate>).GetConstructor(new[] { typeof(List<TNavigate>) }), listValueExp))
@ -1175,6 +1176,124 @@ namespace FreeSql.Internal.CommonProvider
} }
break; break;
case TableRefType.ArrayToMany: case TableRefType.ArrayToMany:
if (true)
{
var subList = new List<TNavigate>();
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<string, MethodInfo>()).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<Func<TNavigate, bool>>(
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<TNavigate>(selectExp, cancellationToken);
#endif
}
else
{
if (selectExp == null) subList = subSelect.ToList(true);
else subList = subSelect.ToList<TNavigate>(selectExp);
}
if (subList.Any() == false)
{
foreach (var item in list)
setListValue(item, new List<TNavigate>());
return;
}
var dicSubList = subList.ToDictionary(a => EntityUtilExtensions.GetEntityValueWithPropertyName(_orm, tbref.RefEntityType, a, tbref.RefColumns[0].CsName)?.ToString(), a => a);
var parentNavs = new List<string>();
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<TNavigate>();
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<TNavigate>(selectExp, cancellationToken);
#endif
}
else
{
if (selectExp == null) subList = subSelect.ToList(true);
else subList = subSelect.ToList<TNavigate>(selectExp);
}
if (subList.Any() == false)
{
foreach (var item in list)
setListValue(item, new List<TNavigate>());
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; break;
} }
}; };