mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
- 增加 IncludeMany(a => a.Childs).ToList(a => new { a.Childs }) 指定集合属性返回;
This commit is contained in:
parent
59ecfdf288
commit
24e0fcd0af
@ -532,14 +532,5 @@
|
||||
<param name="that"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
|
||||
<summary>
|
||||
批量注入 Repository,可以参考代码自行调整
|
||||
</summary>
|
||||
<param name="services"></param>
|
||||
<param name="globalDataFilter"></param>
|
||||
<param name="assemblies"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
</members>
|
||||
</doc>
|
||||
|
@ -1114,33 +1114,89 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
|
||||
.IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList();
|
||||
var t001 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.model1.id,
|
||||
a.childs,
|
||||
childs2 = a.childs
|
||||
});
|
||||
|
||||
var t1 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var t111 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id,
|
||||
a.model2.childs,
|
||||
childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var t2 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id)))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var t222 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id)))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id,
|
||||
a.model2.childs,
|
||||
childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var t00 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList();
|
||||
var t0001 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.model1.id,
|
||||
a.childs,
|
||||
childs2 = a.childs
|
||||
});
|
||||
|
||||
var t11 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var t1111 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id,
|
||||
a.model2.childs,
|
||||
childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var t22 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id)))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var t2222 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id)))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id,
|
||||
a.model2.childs,
|
||||
childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
//---- Select ----
|
||||
|
||||
@ -1148,33 +1204,77 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
|
||||
.IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList();
|
||||
var at001 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.model2id, a.childs, childs2 = a.childs
|
||||
});
|
||||
|
||||
var at1 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var at111 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id, a.model2.childs, childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var at2 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TestInclude_OneToManyModel4 { id = m4.id })))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var at2222 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TestInclude_OneToManyModel4 { id = m4.id })))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id, a.model2.childs, childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var at00 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList();
|
||||
var at011 = g.sqlite.Select<TestInclude_OneToManyModel2>()
|
||||
.IncludeMany(a => a.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.model2id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.model2id, a.childs, childs2 = a.childs
|
||||
});
|
||||
|
||||
var at11 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var at1112 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id, a.model2.childs, childs2 = a.model2.childs
|
||||
});
|
||||
|
||||
var at22 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TestInclude_OneToManyModel4 { id = m4.id })))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList();
|
||||
var at2223 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||
.IncludeMany(a => a.model2.childs.Take(1).Where(m3 => m3.model2111Idaaa == a.model2.model2id).Select(m3 => new TestInclude_OneToManyModel3 { id = m3.id }),
|
||||
then => then.IncludeMany(m3 => m3.childs2.Take(2).Where(m4 => m4.model3333Id333 == m3.id).Select(m4 => new TestInclude_OneToManyModel4 { id = m4.id })))
|
||||
.Where(a => a.id <= model1.id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.id, a.model2.childs, childs2 = a.model2.childs
|
||||
});
|
||||
}
|
||||
|
||||
public class TestInclude_OneToManyModel11
|
||||
@ -1557,6 +1657,15 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
|
||||
.IncludeMany(a => a.Tag.Songs.Take(1).Select(b => new Song { Id = b.Id, Title = b.Title }))
|
||||
.Where(a => a.Tag.Id == tag1.Id || a.Tag.Id == tag2.Id)
|
||||
.ToList(true);
|
||||
|
||||
var asongs2222 = g.sqlite.Select<Song>()
|
||||
.IncludeMany(a => a.Tags.Select(b => new Tag { Id = b.Id, Name = b.Name }),
|
||||
then => then.IncludeMany(t => t.Songs.Select(b => new Song { Id = b.Id, Title = b.Title })))
|
||||
.Where(a => a.Id == song1.Id || a.Id == song2.Id || a.Id == song3.Id)
|
||||
.ToList(a => new
|
||||
{
|
||||
a.Id, a.Is_deleted, a.Tags
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -28,13 +28,13 @@ namespace FreeSql.Internal
|
||||
}
|
||||
|
||||
internal const int ReadAnonymousFieldAsCsName = -53129;
|
||||
public bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, SelectGroupingProvider grouping, List<LambdaExpression> whereCascadeExpression, bool isAllDtoMap)
|
||||
public bool ReadAnonymousField(List<SelectTableInfo> _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Select0Provider select, SelectGroupingProvider grouping, List<LambdaExpression> whereCascadeExpression, List<string> findIncludeMany, bool isAllDtoMap)
|
||||
{
|
||||
Func<ExpTSC> getTSC = () => new ExpTSC { _tables = _tables, grouping = grouping, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression };
|
||||
switch (exp.NodeType)
|
||||
{
|
||||
case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, grouping, whereCascadeExpression, isAllDtoMap);
|
||||
case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, grouping, whereCascadeExpression, isAllDtoMap);
|
||||
case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, grouping, whereCascadeExpression, findIncludeMany, isAllDtoMap);
|
||||
case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, select, grouping, whereCascadeExpression, findIncludeMany, isAllDtoMap);
|
||||
case ExpressionType.Negate:
|
||||
case ExpressionType.NegateChecked:
|
||||
parent.DbField = $"-({ExpressionLambdaToSql(exp, getTSC())})";
|
||||
@ -43,7 +43,7 @@ namespace FreeSql.Internal
|
||||
else if (index == ReadAnonymousFieldAsCsName && string.IsNullOrEmpty(parent.CsName) == false) field.Append(_common.FieldAsAlias(parent.CsName));
|
||||
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
|
||||
return false;
|
||||
case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, grouping, whereCascadeExpression, isAllDtoMap);
|
||||
case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, grouping, whereCascadeExpression, findIncludeMany, isAllDtoMap);
|
||||
case ExpressionType.Constant:
|
||||
var constExp = exp as ConstantExpression;
|
||||
//处理自定义SQL语句,如: ToList(new {
|
||||
@ -133,12 +133,36 @@ namespace FreeSql.Internal
|
||||
MapType = memProp.PropertyType
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.MakeMemberAccess(exp, memProp), grouping, whereCascadeExpression, false);
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.MakeMemberAccess(exp, memProp), select, grouping, whereCascadeExpression, findIncludeMany, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (select != null && findIncludeMany != null && select._includeToList.Any() && exp.Type.IsGenericType &&
|
||||
typeof(IEnumerable).IsAssignableFrom(exp.Type) &&
|
||||
typeof(ICollection<>).MakeGenericType(exp.Type.GetGenericArguments().FirstOrDefault()).IsAssignableFrom(exp.Type))
|
||||
{
|
||||
var includeKey = "";
|
||||
var memExp = exp as MemberExpression;
|
||||
while (memExp != null)
|
||||
{
|
||||
includeKey = $"{memExp.Member.Name}.{includeKey}";
|
||||
if (memExp.Expression.NodeType == ExpressionType.Parameter) break;
|
||||
memExp = memExp.Expression as MemberExpression;
|
||||
}
|
||||
if (memExp != null && string.IsNullOrEmpty(includeKey) == false)
|
||||
{
|
||||
includeKey = includeKey.TrimEnd('.');
|
||||
if (select._includeInfo.ContainsKey(includeKey))
|
||||
{
|
||||
parent.IncludeManyKey = includeKey;
|
||||
parent.CsType = exp.Type.GetGenericArguments().FirstOrDefault();
|
||||
findIncludeMany?.Add(includeKey);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (grouping != null && exp is MemberExpression expMem2 && expMem2.Member.Name == "Key" && expMem2.Expression.Type.FullName.StartsWith("FreeSql.ISelectGroupingAggregate`"))
|
||||
{
|
||||
field.Append(grouping._field);
|
||||
@ -173,7 +197,7 @@ namespace FreeSql.Internal
|
||||
MapType = initExp.NewExpression.Arguments[a].Type
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], grouping, whereCascadeExpression, false);
|
||||
ReadAnonymousField(_tables, field, child, ref index, initExp.NewExpression.Arguments[a], select, grouping, whereCascadeExpression, findIncludeMany, false);
|
||||
}
|
||||
}
|
||||
else if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type)
|
||||
@ -196,7 +220,7 @@ namespace FreeSql.Internal
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
if (dtTb.Parameter != null)
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), grouping, whereCascadeExpression, isAllDtoMap);
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, grouping, whereCascadeExpression, findIncludeMany, isAllDtoMap);
|
||||
else
|
||||
{
|
||||
child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}";
|
||||
@ -222,7 +246,7 @@ namespace FreeSql.Internal
|
||||
MapType = initAssignExp.Expression.Type
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, grouping, whereCascadeExpression, false);
|
||||
ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, select, grouping, whereCascadeExpression, findIncludeMany, false);
|
||||
}
|
||||
}
|
||||
if (parent.Childs.Any() == false) throw new Exception($"映射异常:{initExp.NewExpression.Type.Name} 没有一个属性名相同");
|
||||
@ -255,7 +279,7 @@ namespace FreeSql.Internal
|
||||
MapType = newExp.Arguments[a].Type
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], grouping, whereCascadeExpression, false);
|
||||
ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], select, grouping, whereCascadeExpression, findIncludeMany, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -279,7 +303,7 @@ namespace FreeSql.Internal
|
||||
};
|
||||
parent.Childs.Add(child);
|
||||
if (dtTb.Parameter != null)
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), grouping, whereCascadeExpression, isAllDtoMap);
|
||||
ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), select, grouping, whereCascadeExpression, findIncludeMany, isAllDtoMap);
|
||||
else
|
||||
{
|
||||
child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}";
|
||||
@ -300,9 +324,9 @@ namespace FreeSql.Internal
|
||||
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
|
||||
return false;
|
||||
}
|
||||
public object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead, ReadAnonymousDbValueRef dbValue)
|
||||
public object ReadAnonymous(ReadAnonymousTypeInfo parent, DbDataReader dr, ref int index, bool notRead, ReadAnonymousDbValueRef dbValue, int rowIndex, List<NativeTuple<string, IList, int>> fillIncludeMany)
|
||||
{
|
||||
if (parent.Childs.Any() == false)
|
||||
if (parent.Childs.Any() == false && string.IsNullOrEmpty(parent.IncludeManyKey))
|
||||
{
|
||||
if (notRead)
|
||||
{
|
||||
@ -322,13 +346,18 @@ namespace FreeSql.Internal
|
||||
}
|
||||
var ctorParmsLength = 0;
|
||||
object ret;
|
||||
if (parent.IsDefaultCtor || parent.IsEntity || (ctorParmsLength = parent.Consturctor.GetParameters()?.Length ?? 0) == 0)
|
||||
if (string.IsNullOrEmpty(parent.IncludeManyKey) == false)
|
||||
{
|
||||
ret = typeof(List<>).MakeGenericType(parent.CsType).CreateInstanceGetDefaultValue();
|
||||
fillIncludeMany?.Add(NativeTuple.Create(parent.IncludeManyKey, ret as IList, rowIndex));
|
||||
}
|
||||
else if (parent.IsDefaultCtor || parent.IsEntity || (ctorParmsLength = parent.Consturctor.GetParameters()?.Length ?? 0) == 0)
|
||||
ret = parent.CsType?.CreateInstanceGetDefaultValue() ?? parent.Consturctor.Invoke(null);
|
||||
else
|
||||
{
|
||||
var ctorParms = new object[ctorParmsLength];
|
||||
for (var c = 0; c < ctorParmsLength; c++)
|
||||
ctorParms[c] = ReadAnonymous(parent.Childs[c], dr, ref index, notRead, null);
|
||||
ctorParms[c] = ReadAnonymous(parent.Childs[c], dr, ref index, notRead, null, rowIndex, fillIncludeMany);
|
||||
ret = parent.Consturctor.Invoke(ctorParms);
|
||||
}
|
||||
|
||||
@ -337,7 +366,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
var prop = parent.Childs[b].Property;
|
||||
var dbval = parent.IsEntity ? new ReadAnonymousDbValueRef() : null;
|
||||
var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead, dbval);
|
||||
var objval = ReadAnonymous(parent.Childs[b], dr, ref index, notRead, dbval, rowIndex, fillIncludeMany);
|
||||
if (isnull == false && parent.IsEntity && dbval.DbValue == null && parent.Table != null && parent.Table.ColumnsByCs.TryGetValue(parent.Childs[b].CsName, out var trycol) && trycol.Attribute.IsPrimary)
|
||||
isnull = true;
|
||||
if (isnull == false && prop.CanWrite)
|
||||
|
@ -37,6 +37,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
#else
|
||||
public List<Func<object, Task>> _includeToListAsync = new List<Func<object, Task>>();
|
||||
#endif
|
||||
public Dictionary<string, MemberExpression[]> _includeInfo = new Dictionary<string, MemberExpression[]>();
|
||||
public bool _distinct;
|
||||
public Expression _selectExpression;
|
||||
public List<LambdaExpression> _whereCascadeExpression = new List<LambdaExpression>();
|
||||
@ -57,6 +58,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
#else
|
||||
_includeToListAsync.Clear();
|
||||
#endif
|
||||
_includeInfo.Clear();
|
||||
_selectExpression = null;
|
||||
_whereCascadeExpression.Clear();
|
||||
_whereGlobalFilter = _orm.GlobalFilter.GetFilters();
|
||||
|
@ -85,6 +85,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var ret = new List<T1>();
|
||||
var retCount = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
@ -95,8 +96,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
var idx = af.FieldCount - 1;
|
||||
foreach (var other in otherData)
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null));
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null, retCount, null));
|
||||
}
|
||||
retCount++;
|
||||
}, CommandType.Text, sql, dbParms);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -143,13 +145,13 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_orm.Ado.ExecuteReader(_connection, _transaction, fetch =>
|
||||
{
|
||||
ret.Object.Add(af.Read(_orm, fetch.Object));
|
||||
retCount++;
|
||||
if (otherData != null)
|
||||
{
|
||||
var idx = af.FieldCount - 1;
|
||||
foreach (var other in otherData)
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null));
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null, ret.Object.Count - 1, null));
|
||||
}
|
||||
retCount++;
|
||||
if (chunkSize > 0 && chunkSize == ret.Object.Count)
|
||||
{
|
||||
checkDoneTimes++;
|
||||
@ -219,7 +221,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
_orm.Ado.ExecuteReader(_connection, _transaction, fetch =>
|
||||
{
|
||||
var index = -1;
|
||||
ret.Object.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null));
|
||||
ret.Object.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null, ret.Object.Count, af.fillIncludeMany));
|
||||
retCount++;
|
||||
if (chunkSize > 0 && chunkSize == ret.Object.Count)
|
||||
{
|
||||
@ -300,16 +302,18 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var ret = new List<TReturn>();
|
||||
var retCount = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
_orm.Ado.ExecuteReader(_connection, _transaction, fetch =>
|
||||
{
|
||||
var index = -1;
|
||||
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null));
|
||||
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null, retCount, af.fillIncludeMany));
|
||||
if (otherData != null)
|
||||
foreach (var other in otherData)
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref index, false, null));
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref index, false, null, retCount, null));
|
||||
retCount++;
|
||||
}, CommandType.Text, sql, dbParms);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@ -349,7 +353,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0;
|
||||
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null, _whereCascadeExpression, true);
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, this, null, _whereCascadeExpression, null, true);
|
||||
return new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null);
|
||||
}
|
||||
static ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo> _dicGetAllFieldExpressionTree = new ConcurrentDictionary<string, GetAllFieldExpressionTreeInfo>();
|
||||
@ -652,7 +656,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = -10000; //临时规则,不返回 as1
|
||||
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null, _whereCascadeExpression, false); //不走 DTO 映射
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null, null, _whereCascadeExpression, null, false); //不走 DTO 映射,不处理 IncludeMany
|
||||
var sql = field.ToString();
|
||||
this.GroupBy(sql.Length > 0 ? sql.Substring(2) : null);
|
||||
return new SelectGroupingProvider<TKey, TValue>(_orm, this, map, sql, _commonExpression, _tables);
|
||||
@ -711,7 +715,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = 0;
|
||||
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression, false); //不走 DTO 映射
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, null, _whereCascadeExpression, null, false); //不走 DTO 映射,不处理 IncludeMany
|
||||
return this.ToListMapReader<TReturn>(new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault();
|
||||
}
|
||||
|
||||
@ -788,6 +792,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var ret = new List<T1>();
|
||||
var retCount = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
@ -798,8 +803,9 @@ namespace FreeSql.Internal.CommonProvider
|
||||
{
|
||||
var idx = af.FieldCount - 1;
|
||||
foreach (var other in otherData)
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null));
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref idx, false, null, retCount, null));
|
||||
}
|
||||
retCount++;
|
||||
return Task.FromResult(false);
|
||||
}, CommandType.Text, sql, dbParms);
|
||||
}
|
||||
@ -876,16 +882,18 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms);
|
||||
_orm.Aop.CurdBeforeHandler?.Invoke(this, before);
|
||||
var ret = new List<TReturn>();
|
||||
var retCount = 0;
|
||||
Exception exception = null;
|
||||
try
|
||||
{
|
||||
await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, fetch =>
|
||||
{
|
||||
var index = -1;
|
||||
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null));
|
||||
ret.Add((TReturn)_commonExpression.ReadAnonymous(af.map, fetch.Object, ref index, false, null, retCount, af.fillIncludeMany));
|
||||
if (otherData != null)
|
||||
foreach (var other in otherData)
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref index, false, null));
|
||||
other.retlist.Add(_commonExpression.ReadAnonymous(other.read, fetch.Object, ref index, false, null, retCount, null));
|
||||
retCount++;
|
||||
return Task.FromResult(false);
|
||||
}, CommandType.Text, sql, dbParms);
|
||||
}
|
||||
@ -963,7 +971,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = 0;
|
||||
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression, false); //不走 DTO 映射
|
||||
_commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, null, _whereCascadeExpression, null, false); //不走 DTO 映射,不处理 IncludeMany
|
||||
return (await this.ToListMapReaderAsync<TReturn>(new ReadAnonymousTypeAfInfo(map, field.Length > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault();
|
||||
}
|
||||
#endif
|
||||
|
@ -170,11 +170,84 @@ namespace FreeSql.Internal.CommonProvider
|
||||
return this.InternalSum(column.Body);
|
||||
}
|
||||
|
||||
class IncludeManyNewInit
|
||||
{
|
||||
public TableInfo Table { get; }
|
||||
public Dictionary<string, IncludeManyNewInit> Childs { get; } = new Dictionary<string, IncludeManyNewInit>();
|
||||
public Expression CurrentExpression { get; }
|
||||
public bool IsOutputPrimary { get; set; }
|
||||
public IncludeManyNewInit(TableInfo table, Expression currentExpression)
|
||||
{
|
||||
this.Table = table;
|
||||
this.CurrentExpression = currentExpression;
|
||||
}
|
||||
}
|
||||
public List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select)
|
||||
{
|
||||
if (select == null) return this.InternalToList<TReturn>(select?.Body);
|
||||
_tables[0].Parameter = select.Parameters[0];
|
||||
return this.InternalToList<TReturn>(select.Body);
|
||||
if (_includeToList?.Any() != true) return this.InternalToList<TReturn>(select.Body);
|
||||
|
||||
var findIncludeMany = new List<string>();
|
||||
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 this.ToListMapReaderPrivate<TReturn>(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<MemberBinding>();
|
||||
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 this.ToListMapReaderPrivate<TReturn>(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<object>();
|
||||
var otherAf = new ReadAnonymousTypeOtherInfo(field.ToString(), otherMap, otherRet);
|
||||
|
||||
af.fillIncludeMany = new List<NativeTuple<string, IList, int>>();
|
||||
var ret = this.ToListMapReaderPrivate<TReturn>(af, new[] { otherAf });
|
||||
this.SetList(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 List<TDto> ToList<TDto>() => ToList(GetToListDtoSelector<TDto>());
|
||||
Expression<Func<T1, TDto>> GetToListDtoSelector<TDto>()
|
||||
@ -1031,6 +1104,11 @@ namespace FreeSql.Internal.CommonProvider
|
||||
});
|
||||
_includeToListAsync.Add(listObj => includeToListSyncOrAsync(listObj, true));
|
||||
#endif
|
||||
var includeValue = new MemberExpression[members.Count + 1];
|
||||
for (var a = 0; a < members.Count; a++) includeValue[a] = members[a];
|
||||
includeValue[includeValue.Length - 1] = expBody as MemberExpression;
|
||||
var includeKey = $"{string.Join(".", includeValue.Select(a => a.Member.Name))}";
|
||||
if (_includeInfo.ContainsKey(includeKey) == false) _includeInfo.Add(includeKey, includeValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = 0;
|
||||
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, this, null, false);
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, null, this, null, null, false);
|
||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType;
|
||||
var method = _select.GetType().GetMethod(isAsync ? "ToListMapReaderAsync" : "ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
method = method.MakeGenericMethod(elementType);
|
||||
@ -118,7 +118,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = 0;
|
||||
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, this, null, false);
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, null, this, null, null, false);
|
||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = elementType;
|
||||
var method = _select.GetType().GetMethod("ToListMapReaderPrivate", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
method = method.MakeGenericMethod(elementType);
|
||||
@ -132,7 +132,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = fieldAlias == FieldAliasOptions.AsProperty ? CommonExpression.ReadAnonymousFieldAsCsName : 0;
|
||||
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, this, null, false);
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, select, null, this, null, null, false);
|
||||
var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) });
|
||||
return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string;
|
||||
}
|
||||
@ -210,7 +210,7 @@ namespace FreeSql.Internal.CommonProvider
|
||||
var field = new StringBuilder();
|
||||
var index = 0;
|
||||
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, this, null, false);
|
||||
_comonExp.ReadAnonymousField(null, field, map, ref index, elementSelector, null, this, null, null, false);
|
||||
if (map.Childs.Any() == false && map.MapType == null) map.MapType = typeof(TElement);
|
||||
var method = _select.GetType().GetMethod("ToListMapReaderPrivateAsync", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
method = method.MakeGenericMethod(typeof(TElement));
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
@ -17,6 +18,7 @@ namespace FreeSql.Internal.Model
|
||||
public TableInfo Table { get; set; }
|
||||
public bool IsEntity { get; set; }
|
||||
public bool IsDefaultCtor { get; set; }
|
||||
public string IncludeManyKey { get; set; } //ToList(a => new { a.Childs }) 集合属性指定加载
|
||||
|
||||
public void CopyTo(ReadAnonymousTypeInfo target)
|
||||
{
|
||||
@ -30,12 +32,14 @@ namespace FreeSql.Internal.Model
|
||||
target.Table = Table;
|
||||
target.IsEntity = IsEntity;
|
||||
target.IsDefaultCtor = IsDefaultCtor;
|
||||
target.IncludeManyKey = IncludeManyKey;
|
||||
}
|
||||
}
|
||||
public class ReadAnonymousTypeAfInfo
|
||||
{
|
||||
public ReadAnonymousTypeInfo map { get; }
|
||||
public string field { get; }
|
||||
public List<NativeTuple<string, IList, int>> fillIncludeMany { get; set; } //回填集合属性的数据
|
||||
public ReadAnonymousTypeAfInfo(ReadAnonymousTypeInfo map, string field)
|
||||
{
|
||||
this.map = map;
|
||||
|
Loading…
x
Reference in New Issue
Block a user