- 优化 IncludeByPropertyName + AsType;

This commit is contained in:
2881099 2022-08-23 17:17:37 +08:00
parent d5ab7d0d39
commit 91d6864388
6 changed files with 302 additions and 174 deletions

View File

@ -800,5 +800,14 @@
<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>

View File

@ -1569,6 +1569,84 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title]
.IncludeByPropertyName("Songs")
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
.ToList();
var tags3339 = g.sqlserver.Select<Tag>()
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
.ToList();
tags3339
.IncludeByPropertyName(g.sqlserver, "Tags",
then: then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName(g.sqlserver, "Parent")
.IncludeByPropertyName(g.sqlserver, "Songs");
var tags33331 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.IncludeByPropertyName("Tags")
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
var tags333319 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
tags333319.IncludeByPropertyName(g.sqlserver, "Tags");
var tags3333 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.IncludeByPropertyName("Tags",
then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName("Parent")
.IncludeByPropertyName("Songs")
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
var tags33339 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
tags33339
.IncludeByPropertyName(g.sqlserver, "Tags",
then: then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName(g.sqlserver, "Parent")
.IncludeByPropertyName(g.sqlserver, "Songs");
var tags33333 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.IncludeByPropertyName("Parent.Tags",
then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName("Songs")
.Where(a => (a as Tag).Id == tag1_1.Id || (a as Tag).Id == tag1_1.Id)
.ToList();
var tags333339 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.Where(a => (a as Tag).Id == tag1_1.Id || (a as Tag).Id == tag1_1.Id)
.ToList();
tags333339
.IncludeByPropertyName(g.sqlserver, "Parent.Tags",
then: then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName(g.sqlserver, "Songs");
var tags333333 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.IncludeByPropertyName("Parent.Tags",
then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName("Songs")
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
var tags3333339 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.Where(a => (a as Tag).Id == tag1.Id || (a as Tag).Id == tag2.Id)
.ToList();
tags3333339
.IncludeByPropertyName(g.sqlserver, "Parent.Tags",
select: "Id, Name",
then: then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
.IncludeByPropertyName(g.sqlserver, "Songs");
var tags33333391 = g.sqlserver.Select<object>()
.AsType(typeof(Tag))
.Where(a => (a as Tag).Id == tag1_1.Id || (a as Tag).Id == tag2_1.Id)
.ToList();
tags33333391
.IncludeByPropertyName(g.sqlserver, "Parent.Tags",
select: "Id, Name")
.IncludeByPropertyName(g.sqlserver, "Songs");
var tags11 = g.sqlserver.Select<Tag>()
.IncludeMany(a => a.Tags.Take(1))

View File

@ -378,15 +378,16 @@ public static partial class FreeSqlGlobalExtensions
#endif
IncludeByPropertyNameSyncOrAsync<T1>(bool isAsync, List<T1> list, IFreeSql orm, string property, string where, int take, string select, Expression<Action<ISelect<object>>> then) where T1 : class
{
if (list?.Any() != true) return list;
var entityType = typeof(T1) == typeof(object) ? list[0].GetType() : typeof(T1);
var t1tb = orm.CodeFirst.GetTableByEntity(entityType);
if (orm.CodeFirst.IsAutoSyncStructure)
{
var tb = orm.CodeFirst.GetTableByEntity(typeof(T1));
if (tb == null || tb.Primarys.Any() == false)
(orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(T1)); //._dicSyced.TryAdd(typeof(TReturn), true);
if (t1tb == null || t1tb.Primarys.Any() == false)
(orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(entityType); //._dicSyced.TryAdd(typeof(TReturn), true);
}
var props = property.Split('.');
var t1tb = orm.CodeFirst.GetTableByEntity(typeof(T1));
var t1sel = orm.Select<T1>() as Select1Provider<T1>;
var t1sel = orm.Select<object>().AsType(entityType) as Select1Provider<object>;
var t1expFul = t1sel.ConvertStringPropertyToExpression(property, true);
var t1exp = props.Length == 1 ? t1expFul : t1sel.ConvertStringPropertyToExpression(props[0], true);
if (t1expFul == null) throw new ArgumentException(CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property)));
@ -395,7 +396,7 @@ public static partial class FreeSqlGlobalExtensions
{
if (props.Length > 1)
IncludeByPropertyName(list, orm, string.Join(".", props.Take(props.Length - 1)));
var imsel = IncludeManyByPropertyNameCommonGetSelect<T1>(orm, property, where, take, select, then);
var imsel = IncludeManyByPropertyNameCommonGetSelect(orm, entityType, property, where, take, select, then);
#if net40
imsel.SetList(list);
#else
@ -409,10 +410,8 @@ public static partial class FreeSqlGlobalExtensions
var reftb = orm.CodeFirst.GetTableByEntity(t1exp.Type);
var refsel = orm.Select<object>().AsType(t1exp.Type) as Select1Provider<object>;
if (props.Length > 1)
{
var refexp = refsel.ConvertStringPropertyToExpression(string.Join(".", props.Skip(1)), true);
refsel.Include(Expression.Lambda<Func<object, object>>(refexp, refsel._tables[0].Parameter));
}
refsel.IncludeByPropertyName(string.Join(".", props.Skip(1)));
var listdic = list.Select(item =>
{
var refitem = t1exp.Type.CreateInstanceGetDefaultValue();
@ -444,15 +443,15 @@ public static partial class FreeSqlGlobalExtensions
});
return list;
}
static Select1Provider<T1> IncludeManyByPropertyNameCommonGetSelect<T1>(IFreeSql orm, string property, string where, int take, string select, Expression<Action<ISelect<object>>> then) where T1 : class
static Select1Provider<object> IncludeManyByPropertyNameCommonGetSelect(IFreeSql orm, Type entityType, string property, string where, int take, string select, Expression<Action<ISelect<object>>> then)
{
if (orm.CodeFirst.IsAutoSyncStructure)
{
var tb = orm.CodeFirst.GetTableByEntity(typeof(T1));
var tb = orm.CodeFirst.GetTableByEntity(entityType);
if (tb == null || tb.Primarys.Any() == false)
(orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(typeof(T1)); //._dicSyced.TryAdd(typeof(TReturn), true);
(orm.CodeFirst as CodeFirstProvider)._dicSycedTryAdd(entityType); //._dicSyced.TryAdd(typeof(TReturn), true);
}
var sel = orm.Select<T1>() as Select1Provider<T1>;
var sel = orm.Select<object>().AsType(entityType) as Select1Provider<object>;
var exp = sel.ConvertStringPropertyToExpression(property, true);
if (exp == null) throw new ArgumentException(CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property)));
var memExp = exp as MemberExpression;
@ -521,7 +520,13 @@ public static partial class FreeSqlGlobalExtensions
newthen = newthenLambda.Compile();
}
var funcType = typeof(Func<,>).MakeGenericType(sel._tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(reftb.Type));
var funcType = typeof(Func<,>).MakeGenericType(typeof(object), typeof(IEnumerable<>).MakeGenericType(reftb.Type));
if (sel._tables[0].Table.Type != typeof(object))
{
var expParm = Expression.Parameter(typeof(object), sel._tables[0].Alias);
exp = new Select0Provider.ReplaceMemberExpressionVisitor().Replace(exp, sel._tables[0].Parameter, Expression.Convert(expParm, sel._tables[0].Table.Type));
sel._tables[0].Parameter = expParm;
}
var navigateSelector = Expression.Lambda(funcType, exp, sel._tables[0].Parameter);
var incMethod = sel.GetType().GetMethod("IncludeMany");
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);

View File

@ -3806,184 +3806,201 @@
</summary>
</member>
<member name="P:FreeSql.Aop.TraceAfterEventArgs.Exception">
<summary>
发生的错误
反序列化
</summary>
</member>
<member name="P:FreeSql.Aop.TraceAfterEventArgs.ElapsedTicks">
<summary>
耗时单位Ticks
</summary>
</member>
<member name="P:FreeSql.Aop.TraceAfterEventArgs.ElapsedMilliseconds">
<summary>
耗时(单位:毫秒)
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsAutoSyncStructure">
<summary>
【开发环境必备】自动同步实体结构到数据库,程序运行中检查实体表是否存在,然后创建或修改
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsSyncStructureToLower">
<summary>
转小写同步结构,适用 PostgreSQL
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsSyncStructureToUpper">
<summary>
转大写同步结构,适用 Oracle/达梦/人大金仓
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsConfigEntityFromDbFirst">
<summary>
将数据库的主键、自增、索引设置导入,适用 DbFirst 模式,无须在实体类型上设置 [Column(IsPrimary)] 或者 ConfigEntity。此功能目前可用于 mysql/sqlserver/postgresql/oracle。<para></para>
本功能会影响 IFreeSql 首次访问的速度。<para></para>
若使用 CodeFirst 创建索引后,又直接在数据库上建了索引,若无本功能下一次 CodeFirst 迁移时数据库上创建的索引将被删除
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsNoneCommandParameter">
<summary>
不使用命令参数化执行,针对 Insert/Update
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsGenerateCommandParameterWithLambda">
<summary>
是否生成命令参数化执行,针对 lambda 表达式解析<para></para>
注意:常量不会参数化,变量才会做参数化<para></para>
var id = 100;
fsql.Select&lt;T&gt;().Where(a => a.id == id) 会参数化<para></para>
fsql.Select&lt;T&gt;().Where(a => a.id == 100) 不会参数化
</summary>
</member>
<member name="P:FreeSql.ICodeFirst.IsLazyLoading">
<summary>
延时加载导航属性对象,导航属性需要声明 virtual
</summary>
</member>
<member name="M:FreeSql.ICodeFirst.GetComparisonDDLStatements``1">
<summary>
将实体类型与数据库对比返回DDL语句
</summary>
<typeparam name="TEntity"></typeparam>
<param name="column"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.GetComparisonDDLStatements(System.Type[])">
<member name="M:FreeSql.IDbFirst.GetEnumsByDatabase(System.String[])">
<summary>
将实体类型集合与数据库对比返回DDL语句
</summary>
<param name="entityTypes">实体类型</param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.GetComparisonDDLStatements(System.Type,System.String)">
<summary>
将实体类型与数据库对比返回DDL语句指定表名
</summary>
<param name="entityType">实体类型</param>
<param name="tableName">指定表名对比</param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.SyncStructure``1">
<summary>
同步实体类型到数据库<para></para>
注意:生产环境中谨慎使用
</summary>
<typeparam name="TEntity"></typeparam>
</member>
<member name="M:FreeSql.ICodeFirst.SyncStructure(System.Type[])">
<summary>
同步实体类型集合到数据库<para></para>
注意:生产环境中谨慎使用
</summary>
<param name="entityTypes"></param>
</member>
<member name="M:FreeSql.ICodeFirst.SyncStructure(System.Type,System.String,System.Boolean)">
<summary>
同步实体类型到数据库(指定表名)<para></para>
注意:生产环境中谨慎使用
</summary>
<param name="entityType">实体类型</param>
<param name="tableName">指定表名对比</param>
<param name="isForceSync">强制同步结构,无视缓存每次都同步</param>
</member>
<member name="M:FreeSql.ICodeFirst.GetDbInfo(System.Type)">
<summary>
根据 System.Type 获取数据库信息
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.ConfigEntity``1(System.Action{FreeSql.DataAnnotations.TableFluent{``0}})">
<summary>
FreeSql FluentApi 配置实体,方法名与特性相同
</summary>
<typeparam name="T"></typeparam>
<param name="entity"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.ConfigEntity(System.Type,System.Action{FreeSql.DataAnnotations.TableFluent})">
<summary>
FreeSql FluentApi 配置实体,方法名与特性相同
</summary>
<param name="type"></param>
<param name="entity"></param>
<returns></returns>
</member>
<member name="M:FreeSql.ICodeFirst.GetConfigEntity(System.Type)">
<summary>
获取 FreeSql FluentApi 配置实体的元数据
</summary>
<param name="type"></param>
<returns>未使用ConfigEntity配置时返回null</returns>
</member>
<member name="M:FreeSql.ICodeFirst.GetTableByEntity(System.Type)">
<summary>
获取实体类核心配置
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetDatabases">
<summary>
获取所有数据库
</summary>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetTablesByDatabase(System.String[])">
<summary>
获取指定数据库的表信息,包括表、列详情、主键、唯一键、索引、外键、备注
获取数据库枚举类型,适用 PostgreSQL
</summary>
<param name="database"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetTableByName(System.String,System.Boolean)">
<member name="F:FreeSql.Internal.BaseDiyMemberExpression._lambdaParameter">
<summary>
获取指定单表信息,包括列详情、主键、唯一键、索引、备注
临时 LambdaExpression.Parameter
</summary>
<param name="name">表名dbo.table1</param>
<param name="ignoreCase">是否忽略大小写</param>
</member>
<member name="M:FreeSql.Internal.CommonProvider.InsertOrUpdateProvider`1.SplitSourceByIdentityValueIsNull(System.Collections.Generic.List{`0})">
<summary>
如果实体类有自增属性,分成两个 List有值的Item1 merge无值的Item2 insert
</summary>
<param name="source"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.ExistsTable(System.String,System.Boolean)">
<member name="M:FreeSql.Internal.CommonProvider.InsertProvider`1.IgnoreCanInsert">
<summary>
判断表是否存在
AsType, Ctor, ClearData 三处地方需要重新加载
</summary>
<param name="name">表名dbo.table1</param>
<param name="ignoreCase">是否忽略大小写</param>
</member>
<member name="M:FreeSql.Internal.CommonProvider.UpdateProvider`1.IgnoreCanUpdate">
<summary>
AsType, Ctor, ClearData 三处地方需要重新加载
</summary>
</member>
<member name="M:FreeSql.Internal.CommonUtils.GetPropertyCommentByDescriptionAttribute(System.Type)">
<summary>
动态读取 DescriptionAttribute 注释文本
</summary>
<param name="type"></param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetDbType(FreeSql.DatabaseModel.DbColumnInfo)">
<member name="M:FreeSql.Internal.CommonUtils.GetProperyCommentBySummary(System.Type)">
<summary>
获取数据库枚举类型int值
通过属性的注释文本,通过 xml 读取
</summary>
<param name="column"></param>
<param name="type"></param>
<returns>Dictkey=属性名value=注释</returns>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.Table">
<summary>
更新实体的元数据
</summary>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.Sql">
<summary>
执行更新的 SQL
</summary>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.DbParams">
<summary>
执行更新命令的参数
</summary>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.Affrows">
<summary>
执行更新命令影响的行
</summary>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.EntitySourceCount">
<summary>
更新的实体数量
</summary>
</member>
<member name="P:FreeSql.Internal.DbUpdateVersionException.EntitySource">
<summary>
更新的实体
</summary>
</member>
<member name="T:FreeSql.Internal.MappingPriorityType">
<summary>
映射优先级,默认: Attribute > FluentApi > Aop
</summary>
</member>
<member name="F:FreeSql.Internal.MappingPriorityType.Attribute">
<summary>
实体特性<para></para>
[Table(Name = "tabname")]<para></para>
[Column(Name = "table_id")]
</summary>
</member>
<member name="F:FreeSql.Internal.MappingPriorityType.FluentApi">
<summary>
流式接口<para></para>
fsql.CodeFirst.ConfigEntity(a => a.Name("tabname"))<para></para>
fsql.CodeFirst.ConfigEntity(a => a.Property(b => b.Id).Name("table_id"))
</summary>
</member>
<member name="F:FreeSql.Internal.MappingPriorityType.Aop">
<summary>
AOP 特性 https://github.com/dotnetcore/FreeSql/wiki/AOP<para></para>
fsql.Aop.ConfigEntity += (_, e) => e.ModifyResult.Name = "public.tabname";<para></para>
fsql.Aop.ConfigEntityProperty += (_, e) => e.ModifyResult.Name = "table_id";<para></para>
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.None">
<summary>
不进行任何处理
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscore">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串
<para></para>
BigApple -> Big_Apple
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscoreWithUpper">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
<para></para>
BigApple -> BIG_APPLE
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.PascalCaseToUnderscoreWithLower">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
<para></para>
BigApple -> big_apple
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.ToUpper">
<summary>
将字符串转换为大写
<para></para>
BigApple -> BIGAPPLE
</summary>
</member>
<member name="F:FreeSql.Internal.NameConvertType.ToLower">
<summary>
将字符串转换为小写
<para></para>
BigApple -> bigapple
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.None">
<summary>
不进行任何处理
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscore">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串
<para></para>
BigApple -> Big_Apple
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithUpper">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全大写
<para></para>
BigApple -> BIG_APPLE
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.PascalCaseToUnderscoreWithLower">
<summary>
将帕斯卡命名字符串转换为下划线分隔字符串,且转换为全小写
<para></para>
BigApple -> big_apple
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.Upper">
<summary>
将字符串转换为大写
<para></para>
BigApple -> BIGAPPLE
</summary>
</member>
<member name="F:FreeSql.Internal.StringConvertType.Lower">
<summary>
将字符串转换为小写
<para></para>
BigApple -> bigapple
</summary>
</member>
<member name="M:FreeSql.Internal.GlobalFilter.Apply``1(System.String,System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
<summary>
创建一个过滤器<para></para>
提示:在 Lambda 中判断登陆身份,请参考资料 AsyncLocal
</summary>
<typeparam name="TEntity"></typeparam>
<param name="name">名字</param>
<param name="where">表达式</param>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetCsConvert(FreeSql.DatabaseModel.DbColumnInfo)">
<summary>
获取c#转换,(int)、(long)
</summary>
<param name="column"></param>
<member name="M:FreeSql.Internal.GlobalFilter.ApplyIf``1(System.String,System.Funm>
<returns></returns>
</member>
<member name="M:FreeSql.IDbFirst.GetCsTypeValue(FreeSql.DatabaseModel.DbColumnInfo)">

View File

@ -498,6 +498,8 @@ namespace FreeSql.Internal.CommonProvider
protected override Expression VisitMember(MemberExpression node)
{
if (_findExp == node) return _replaceExp;
if (node.Expression?.NodeType == ExpressionType.Parameter && node.Expression == _findExp)
return Expression.Property(_replaceExp, node.Member.Name);
return base.VisitMember(node);
}
}

View File

@ -491,7 +491,13 @@ namespace FreeSql.Internal.CommonProvider
case TableRefType.ManyToMany:
case TableRefType.OneToMany:
case TableRefType.PgArrayToMany:
var funcType = typeof(Func<,>).MakeGenericType(_tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(parTbref.RefEntityType));
var funcType = typeof(Func<,>).MakeGenericType(typeof(T1), typeof(IEnumerable<>).MakeGenericType(parTbref.RefEntityType));
if (_tables[0].Table.Type != typeof(T1))
{
var expParm = Expression.Parameter(typeof(T1), _tables[0].Alias);
exp = new ReplaceMemberExpressionVisitor().Replace(exp, _tables[0].Parameter, Expression.Convert(expParm, _tables[0].Table.Type));
_tables[0].Parameter = expParm;
}
var navigateSelector = Expression.Lambda(funcType, exp, _tables[0].Parameter);
var incMethod = this.GetType().GetMethod("IncludeMany");
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);
@ -580,6 +586,15 @@ namespace FreeSql.Internal.CommonProvider
param = tmpExp as ParameterExpression;
isbreak = true;
break;
case ExpressionType.Convert:
var convertExp = tmpExp as UnaryExpression;
if (convertExp?.Operand.NodeType == ExpressionType.Parameter)
{
param = convertExp.Operand as ParameterExpression;
isbreak = true;
break;
}
throw new Exception(CoreStrings.Expression_Error_Use_Successive_MemberAccess_Type(exp));
default:
throw new Exception(CoreStrings.Expression_Error_Use_Successive_MemberAccess_Type(exp));
}
@ -769,6 +784,7 @@ namespace FreeSql.Internal.CommonProvider
var t1parm = Expression.Parameter(typeof(T1));
Expression membersExp = t1parm;
Expression membersExpNotNull = null;
if (typeof(T1) != _tables[0].Table.Type) membersExp = Expression.TypeAs(membersExp, _tables[0].Table.Type);
foreach (var mem in members)
{
membersExp = Expression.MakeMemberAccess(membersExp, mem.Member);
@ -863,6 +879,7 @@ namespace FreeSql.Internal.CommonProvider
return getListValue1(item, propName);
};
if (list.Where(a => getListValue1(a, "") == null).Count() == list.Count) return; //Parent.Childs 当 parent 都是 NULL 就没有和要向下查询了
foreach (var item in list)
setListValue(item, null);