mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 18:52:50 +08:00
- 增加 IncludeByPropertyName 重载 then 参数;#1214
This commit is contained in:
parent
65d0ac6185
commit
2450324f28
@ -800,5 +800,14 @@
|
|||||||
<param name="that"></param>
|
<param name="that"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</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>
|
</members>
|
||||||
</doc>
|
</doc>
|
||||||
|
@ -1562,6 +1562,14 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT TOP 10 b.[Title]
|
|||||||
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
var tags333 = g.sqlserver.Select<Tag>()
|
||||||
|
.IncludeByPropertyName("Tags",
|
||||||
|
then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"))
|
||||||
|
.IncludeByPropertyName("Parent")
|
||||||
|
.IncludeByPropertyName("Songs")
|
||||||
|
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var tags11 = g.sqlserver.Select<Tag>()
|
var tags11 = g.sqlserver.Select<Tag>()
|
||||||
.IncludeMany(a => a.Tags.Take(1))
|
.IncludeMany(a => a.Tags.Take(1))
|
||||||
.Include(a => a.Parent)
|
.Include(a => a.Parent)
|
||||||
|
@ -1368,7 +1368,7 @@ FROM ""TestTypeParentInfo_01"" a", asTableSubSql);
|
|||||||
.ToList();
|
.ToList();
|
||||||
by1.IncludeByPropertyName(g.sqlite, "model2.childs", "model2111Idaaa=model2id");
|
by1.IncludeByPropertyName(g.sqlite, "model2.childs", "model2111Idaaa=model2id");
|
||||||
|
|
||||||
by1.IncludeByPropertyNameAsync(g.sqlite, "model2.childs", "model2111Idaaa=model2id");
|
by1.IncludeByPropertyNameAsync(g.sqlite, "model2.childs", "model2111Idaaa=model2id").Wait();
|
||||||
var t1 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
var t1 = g.sqlite.Select<TestInclude_OneToManyModel1>()
|
||||||
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
.IncludeMany(a => a.model2.childs.Where(m3 => m3.model2111Idaaa == a.model2.model2id))
|
||||||
.Where(a => a.id <= model1.id)
|
.Where(a => a.id <= model1.id)
|
||||||
@ -1678,6 +1678,12 @@ FROM ""TestTypeParentInfo_01"" a", asTableSubSql);
|
|||||||
.IncludeMany(a => a.Songs)
|
.IncludeMany(a => a.Songs)
|
||||||
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
var tags3List = g.sqlite.Select<Tag>()
|
||||||
|
.Include(a => a.Parent)
|
||||||
|
.Where(a => a.Id == tag1.Id || a.Id == tag2.Id)
|
||||||
|
.ToList();
|
||||||
|
tags3List.IncludeByPropertyName(g.sqlite, "Tags", then: then => then.IncludeByPropertyName("Parent").IncludeByPropertyName("Songs").IncludeByPropertyName("Tags"));
|
||||||
|
tags3List.IncludeByPropertyName(g.sqlite, "Songs");
|
||||||
|
|
||||||
var tags11 = g.sqlite.Select<Tag>()
|
var tags11 = g.sqlite.Select<Tag>()
|
||||||
.IncludeMany(a => a.Tags.Take(1))
|
.IncludeMany(a => a.Tags.Take(1))
|
||||||
|
@ -20,6 +20,12 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
public static partial class FreeSqlGlobalExtensions
|
public static partial class FreeSqlGlobalExtensions
|
||||||
{
|
{
|
||||||
|
#if net40
|
||||||
|
#else
|
||||||
|
static readonly Lazy<PropertyInfo> _TaskReflectionResultPropertyLazy = new Lazy<PropertyInfo>(() => typeof(Task).GetProperty("Result"));
|
||||||
|
internal static object GetTaskReflectionResult(this Task task) => _TaskReflectionResultPropertyLazy.Value.GetValue(task, new object[0]);
|
||||||
|
#endif
|
||||||
|
|
||||||
#region Type 对象扩展方法
|
#region Type 对象扩展方法
|
||||||
static Lazy<Dictionary<Type, bool>> _dicIsNumberType = new Lazy<Dictionary<Type, bool>>(() => new Dictionary<Type, bool>
|
static Lazy<Dictionary<Type, bool>> _dicIsNumberType = new Lazy<Dictionary<Type, bool>>(() => new Dictionary<Type, bool>
|
||||||
{
|
{
|
||||||
@ -342,26 +348,26 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
/// <param name="orm"></param>
|
/// <param name="orm"></param>
|
||||||
/// <param name="property">选择一个集合或普通属性</param>
|
/// <param name="property">选择一个集合或普通属性</param>
|
||||||
/// <param name="where">设置临时的子集合关系映射,格式:子类属性=T1属性</param>
|
/// <param name="where">设置临时的子集合关系映射,格式:子类属性=T1属性,多组以逗号分割</param>
|
||||||
/// <param name="take">设置子集合只取条数</param>
|
/// <param name="take">设置子集合只取条数</param>
|
||||||
/// <param name="select">设置子集合只查询部分字段</param>
|
/// <param name="select">设置子集合只查询部分字段</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="ArgumentException"></exception>
|
/// <exception cref="ArgumentException"></exception>
|
||||||
public static List<T1> IncludeByPropertyName<T1>(this List<T1> list, IFreeSql orm, string property, string where = null, int take = 0, string select = null) where T1 : class
|
public static List<T1> IncludeByPropertyName<T1>(this List<T1> list, IFreeSql orm, string property, string where = null, int take = 0, string select = null, Expression<Action<ISelect<object>>> then = null) where T1 : class
|
||||||
{
|
{
|
||||||
#if net40
|
#if net40
|
||||||
return IncludeByPropertyNameSyncOrAsync<T1>(false, list, orm, property, where, take, select);
|
return IncludeByPropertyNameSyncOrAsync<T1>(false, list, orm, property, where, take, select, then);
|
||||||
#else
|
#else
|
||||||
var task = IncludeByPropertyNameSyncOrAsync<T1>(false, list, orm, property, where, take, select);
|
var task = IncludeByPropertyNameSyncOrAsync<T1>(false, list, orm, property, where, take, select, then);
|
||||||
if (task.Exception != null) throw task.Exception.InnerException ?? task.Exception;
|
if (task.Exception != null) throw task.Exception.InnerException ?? task.Exception;
|
||||||
return task.Result;
|
return task.Result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if net40
|
#if net40
|
||||||
#else
|
#else
|
||||||
public static Task<List<T1>> IncludeByPropertyNameAsync<T1>(this List<T1> list, IFreeSql orm, string property, string where = null, int take = 0, string select = null) where T1 : class
|
public static Task<List<T1>> IncludeByPropertyNameAsync<T1>(this List<T1> list, IFreeSql orm, string property, string where = null, int take = 0, string select = null, Expression<Action<ISelect<object>>> then = null) where T1 : class
|
||||||
{
|
{
|
||||||
return IncludeByPropertyNameSyncOrAsync<T1>(true, list, orm, property, where, take, select);
|
return IncludeByPropertyNameSyncOrAsync<T1>(true, list, orm, property, where, take, select, then);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
static
|
static
|
||||||
@ -370,7 +376,7 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
#else
|
#else
|
||||||
async Task<List<T1>>
|
async Task<List<T1>>
|
||||||
#endif
|
#endif
|
||||||
IncludeByPropertyNameSyncOrAsync<T1>(bool isAsync, List<T1> list, IFreeSql orm, string property, string where = null, int take = 0, string select = null) where T1 : class
|
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 (orm.CodeFirst.IsAutoSyncStructure)
|
if (orm.CodeFirst.IsAutoSyncStructure)
|
||||||
{
|
{
|
||||||
@ -389,7 +395,7 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
{
|
{
|
||||||
if (props.Length > 1)
|
if (props.Length > 1)
|
||||||
IncludeByPropertyName(list, orm, string.Join(".", props.Take(props.Length - 1)));
|
IncludeByPropertyName(list, orm, string.Join(".", props.Take(props.Length - 1)));
|
||||||
var imsel = IncludeManyByPropertyNameCommonGetSelect<T1>(orm, property, where, take, select);
|
var imsel = IncludeManyByPropertyNameCommonGetSelect<T1>(orm, property, where, take, select, then);
|
||||||
#if net40
|
#if net40
|
||||||
imsel.SetList(list);
|
imsel.SetList(list);
|
||||||
#else
|
#else
|
||||||
@ -438,7 +444,7 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
static Select1Provider<T1> IncludeManyByPropertyNameCommonGetSelect<T1>(IFreeSql orm, string property, string where = null, int take = 0, string select = null) where T1 : class
|
static Select1Provider<T1> IncludeManyByPropertyNameCommonGetSelect<T1>(IFreeSql orm, string property, string where, int take, string select, Expression<Action<ISelect<object>>> then) where T1 : class
|
||||||
{
|
{
|
||||||
if (orm.CodeFirst.IsAutoSyncStructure)
|
if (orm.CodeFirst.IsAutoSyncStructure)
|
||||||
{
|
{
|
||||||
@ -506,12 +512,20 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
memberInitExp = Expression.Lambda(reffuncType, memberInitExp, refparamExp);
|
memberInitExp = Expression.Lambda(reffuncType, memberInitExp, refparamExp);
|
||||||
exp = Expression.Call(refWhereMethod, exp, memberInitExp);
|
exp = Expression.Call(refWhereMethod, exp, memberInitExp);
|
||||||
}
|
}
|
||||||
|
Delegate newthen = null;
|
||||||
|
if (then != null)
|
||||||
|
{
|
||||||
|
var newthenParm = Expression.Parameter(typeof(ISelect<>).MakeGenericType(reftb.Type));
|
||||||
|
var newthenLambdaBody = new Select1Provider<object>.ReplaceIncludeByPropertyNameParameterVisitor().Modify(then, newthenParm);
|
||||||
|
var newthenLambda = Expression.Lambda(typeof(Action<>).MakeGenericType(newthenParm.Type), newthenLambdaBody, newthenParm);
|
||||||
|
newthen = newthenLambda.Compile();
|
||||||
|
}
|
||||||
|
|
||||||
var funcType = typeof(Func<,>).MakeGenericType(sel._tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(reftb.Type));
|
var funcType = typeof(Func<,>).MakeGenericType(sel._tables[0].Table.Type, typeof(IEnumerable<>).MakeGenericType(reftb.Type));
|
||||||
var navigateSelector = Expression.Lambda(funcType, exp, sel._tables[0].Parameter);
|
var navigateSelector = Expression.Lambda(funcType, exp, sel._tables[0].Parameter);
|
||||||
var incMethod = sel.GetType().GetMethod("IncludeMany");
|
var incMethod = sel.GetType().GetMethod("IncludeMany");
|
||||||
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);
|
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);
|
||||||
incMethod.MakeGenericMethod(reftb.Type).Invoke(sel, new object[] { navigateSelector, null });
|
incMethod.MakeGenericMethod(reftb.Type).Invoke(sel, new object[] { navigateSelector, newthen });
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -5606,7 +5606,7 @@
|
|||||||
<param name="then">即能 ThenInclude,还可以二次过滤(这个 EFCore 做不到?)</param>
|
<param name="then">即能 ThenInclude,还可以二次过滤(这个 EFCore 做不到?)</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:FreeSqlGlobalExtensions.IncludeByPropertyName``1(System.Collections.Generic.List{``0},IFreeSql,System.String,System.String,System.Int32,System.String)">
|
<member name="M:FreeSqlGlobalExtensions.IncludeByPropertyName``1(System.Collections.Generic.List{``0},IFreeSql,System.String,System.String,System.Int32,System.String,System.Linq.Expressions.Expression{System.Action{FreeSql.ISelect{System.Object}}})">
|
||||||
<summary>
|
<summary>
|
||||||
本方法实现从已知的内存 List 数据,进行和 ISelect.IncludeMany/Include 相同功能的贪婪加载<para></para>
|
本方法实现从已知的内存 List 数据,进行和 ISelect.IncludeMany/Include 相同功能的贪婪加载<para></para>
|
||||||
集合:new List<Song>(new[] { song1, song2, song3 }).IncludeByPropertyName(fsql, "Tags", "ParentId=Id", 5, "Id,Name");<para></para>
|
集合:new List<Song>(new[] { song1, song2, song3 }).IncludeByPropertyName(fsql, "Tags", "ParentId=Id", 5, "Id,Name");<para></para>
|
||||||
@ -5618,7 +5618,7 @@
|
|||||||
<param name="list"></param>
|
<param name="list"></param>
|
||||||
<param name="orm"></param>
|
<param name="orm"></param>
|
||||||
<param name="property">选择一个集合或普通属性</param>
|
<param name="property">选择一个集合或普通属性</param>
|
||||||
<param name="where">设置临时的子集合关系映射,格式:子类属性=T1属性</param>
|
<param name="where">设置临时的子集合关系映射,格式:子类属性=T1属性,多组以逗号分割</param>
|
||||||
<param name="take">设置子集合只取条数</param>
|
<param name="take">设置子集合只取条数</param>
|
||||||
<param name="select">设置子集合只查询部分字段</param>
|
<param name="select">设置子集合只查询部分字段</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
|
@ -351,6 +351,7 @@ namespace FreeSql
|
|||||||
/// <param name="property"></param>
|
/// <param name="property"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ISelect<T1> IncludeByPropertyName(string property);
|
ISelect<T1> IncludeByPropertyName(string property);
|
||||||
|
ISelect<T1> IncludeByPropertyName(string property, Expression<Action<ISelect<object>>> then);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按属性名字符串进行 Include/IncludeMany 操作
|
/// 按属性名字符串进行 Include/IncludeMany 操作
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -358,6 +359,7 @@ namespace FreeSql
|
|||||||
/// <param name="property"></param>
|
/// <param name="property"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
ISelect<T1> IncludeByPropertyNameIf(bool condition, string property);
|
ISelect<T1> IncludeByPropertyNameIf(bool condition, string property);
|
||||||
|
ISelect<T1> IncludeByPropertyNameIf(bool condition, string property, Expression<Action<ISelect<object>>> then);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实现 select .. from ( select ... from t ) a 这样的功能<para></para>
|
/// 实现 select .. from ( select ... from t ) a 这样的功能<para></para>
|
||||||
|
@ -1441,7 +1441,7 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
|
|
||||||
if (c < ret.Count - 1) continue;
|
if (c < ret.Count - 1) continue;
|
||||||
await diretTask;
|
await diretTask;
|
||||||
var diret = diretTask.GetType().GetProperty("Result").GetValue(diretTask, new object[0]);
|
var diret = diretTask.GetTaskReflectionResult();
|
||||||
var otherList = diret as IEnumerable;
|
var otherList = diret as IEnumerable;
|
||||||
var retlistidx = 0;
|
var retlistidx = 0;
|
||||||
foreach (var otherListItem in otherList)
|
foreach (var otherListItem in otherList)
|
||||||
|
@ -471,8 +471,10 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
|
|
||||||
public int InsertInto<TTargetEntity>(string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class => base.InternalInsertInto<TTargetEntity>(tableName, select);
|
public int InsertInto<TTargetEntity>(string tableName, Expression<Func<T1, TTargetEntity>> select) where TTargetEntity : class => base.InternalInsertInto<TTargetEntity>(tableName, select);
|
||||||
|
|
||||||
public ISelect<T1> IncludeByPropertyNameIf(bool condition, string property) => condition ? IncludeByPropertyName(property) : this;
|
public ISelect<T1> IncludeByPropertyNameIf(bool condition, string property) => condition ? IncludeByPropertyName(property, null) : this;
|
||||||
public ISelect<T1> IncludeByPropertyName(string property)
|
public ISelect<T1> IncludeByPropertyNameIf(bool condition, string property, Expression<Action<ISelect<object>>> then) => condition ? IncludeByPropertyName(property, then) : this;
|
||||||
|
public ISelect<T1> IncludeByPropertyName(string property) => IncludeByPropertyName(property, null);
|
||||||
|
public ISelect<T1> IncludeByPropertyName(string property, Expression<Action<ISelect<object>>> then)
|
||||||
{
|
{
|
||||||
var exp = ConvertStringPropertyToExpression(property, true);
|
var exp = ConvertStringPropertyToExpression(property, true);
|
||||||
if (exp == null) throw new ArgumentException($"{CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property))}");
|
if (exp == null) throw new ArgumentException($"{CoreStrings.Cannot_Resolve_ExpressionTree(nameof(property))}");
|
||||||
@ -491,7 +493,15 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
var navigateSelector = Expression.Lambda(funcType, exp, _tables[0].Parameter);
|
var navigateSelector = Expression.Lambda(funcType, exp, _tables[0].Parameter);
|
||||||
var incMethod = this.GetType().GetMethod("IncludeMany");
|
var incMethod = this.GetType().GetMethod("IncludeMany");
|
||||||
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);
|
if (incMethod == null) throw new Exception(CoreStrings.RunTimeError_Reflection_IncludeMany);
|
||||||
incMethod.MakeGenericMethod(parTbref.RefEntityType).Invoke(this, new object[] { navigateSelector, null });
|
Delegate newthen = null;
|
||||||
|
if (then != null)
|
||||||
|
{
|
||||||
|
var newthenParm = Expression.Parameter(typeof(ISelect<>).MakeGenericType(parTbref.RefEntityType));
|
||||||
|
var newthenLambdaBody = new ReplaceIncludeByPropertyNameParameterVisitor().Modify(then, newthenParm);
|
||||||
|
var newthenLambda = Expression.Lambda(typeof(Action<>).MakeGenericType(newthenParm.Type), newthenLambdaBody, newthenParm);
|
||||||
|
newthen = newthenLambda.Compile();
|
||||||
|
}
|
||||||
|
incMethod.MakeGenericMethod(parTbref.RefEntityType).Invoke(this, new object[] { navigateSelector, newthen });
|
||||||
break;
|
break;
|
||||||
case TableRefType.ManyToOne:
|
case TableRefType.ManyToOne:
|
||||||
case TableRefType.OneToOne:
|
case TableRefType.OneToOne:
|
||||||
@ -502,6 +512,35 @@ namespace FreeSql.Internal.CommonProvider
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
public class ReplaceIncludeByPropertyNameParameterVisitor : ExpressionVisitor
|
||||||
|
{
|
||||||
|
private Expression _replaceExp;
|
||||||
|
private ParameterExpression oldParameter;
|
||||||
|
public Expression Modify(LambdaExpression lambda, Expression replaceExp)
|
||||||
|
{
|
||||||
|
this._replaceExp = replaceExp;
|
||||||
|
this.oldParameter = lambda.Parameters.FirstOrDefault();
|
||||||
|
return Visit(lambda.Body);
|
||||||
|
}
|
||||||
|
protected override Expression VisitMember(MemberExpression node)
|
||||||
|
{
|
||||||
|
if (node.Expression?.NodeType == ExpressionType.Parameter && node.Expression == oldParameter)
|
||||||
|
return Expression.Property(_replaceExp, node.Member.Name);
|
||||||
|
return base.VisitMember(node);
|
||||||
|
}
|
||||||
|
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||||
|
{
|
||||||
|
if (node.Object?.Type == oldParameter.Type)
|
||||||
|
{
|
||||||
|
var methodParameterTypes = node.Method.GetParameters().Select(a => a.ParameterType).ToArray();
|
||||||
|
var method = _replaceExp.Type.GetMethod(node.Method.Name, methodParameterTypes);
|
||||||
|
if (node.Object?.NodeType == ExpressionType.Parameter && node.Object == oldParameter)
|
||||||
|
return Expression.Call(_replaceExp, method, node.Arguments);
|
||||||
|
return Expression.Call(Visit(node.Object), method, node.Arguments);
|
||||||
|
}
|
||||||
|
return base.VisitMethodCall(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool _isIncluded = false;
|
bool _isIncluded = false;
|
||||||
public ISelect<T1> IncludeIf<TNavigate>(bool condition, Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class => condition ? Include(navigateSelector) : this;
|
public ISelect<T1> IncludeIf<TNavigate>(bool condition, Expression<Func<T1, TNavigate>> navigateSelector) where TNavigate : class => condition ? Include(navigateSelector) : this;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user