public static IEnumerable <TableRefTree> GetTableRefTree(IFreeSql orm, TableRefTree tree, int maxLevel, string[] properties = null) { if (tree.Level > maxLevel) { yield break; } var tableRefs = tree.TableInfo.Properties.Where(property => properties == null || string.Equals(properties[tree.Level - 1], property.Key, StringComparison.OrdinalIgnoreCase)).Select(a => tree.TableInfo.GetTableRef(a.Key, false)).Where(a => a != null).ToList(); foreach (var tableRef in tableRefs) { var tableInfo = orm.CodeFirst.GetTableByEntity(tableRef.RefEntityType); var sub = new TableRefTree() { Level = tree.Level + 1, TableInfo = tableInfo, TableRef = tableRef, Parent = tree, }; // 排除重复类型 if (sub.CheckRepeat()) { continue; } sub.Subs = GetTableRefTree(orm, sub, maxLevel, properties).ToList(); yield return(sub); } }
public static Expression <Func <T1, bool> > GetWhereExpression <T1>(ISelect <T1> select, DynamicFilterInfo filter) { var properties = filter.Field.Split('.'); var tree = TableRefTree.GetTableRefTree(select, properties.Length, properties); // 检索 var treeList = GetTreeList(tree).ToList(); var deepest = treeList.Last(); var collectionNodes = treeList.Where(a => a.TableRef.RefType == TableRefType.OneToMany || a.TableRef.RefType == TableRefType.ManyToMany).ToList(); if (deepest.Level != properties.Length) { throw new Exception($"当前类型{typeof(T1)}导航属性{filter.Field}匹配检索失败"); } if (collectionNodes.Count == 0) { throw new Exception($"当前类型{typeof(T1)}导航属性{filter.Field}不包含{TableRefType.OneToMany}或者{nameof(TableRefType.ManyToMany)}关系"); } var selectMethod = typeof(FreeSqlGlobalExtensions).GetMethods().First(a => a.ContainsGenericParameters && a.GetParameters().Count() == 1); var parameterExpression = Expression.Parameter(typeof(T1), "t"); var manyLevel = 0; var exp = GetWhereExpression(select, deepest, filter, properties, null, ref manyLevel); return(exp as Expression <Func <T1, bool> >); }
public static TableRefTree GetTableRefTree <T1>(ISelect <T1> select, int maxLevel, string[] properties = null) { var orm = select.GetType().GetField("_orm").GetValue(select) as IFreeSql; var tableInfo = orm.CodeFirst.GetTableByEntity(typeof(T1)); var tree = new TableRefTree() { Level = 1, TableInfo = tableInfo, }; tree.Subs = GetTableRefTree(orm, tree, maxLevel, properties).ToList(); return(tree); }
private static IEnumerable <TableRefTree> GetTreeList(TableRefTree tree) { if (tree.Subs == null || tree.Subs.Count == 0) { yield break; } yield return(tree.Subs[0]); foreach (var sub in GetTreeList(tree.Subs[0])) { yield return(sub); } }
static bool CheckRepeat(this TableRefTree tree, List <Type> types = null) { if (tree.Parent == null) { return(false); } if (types == null) { types = new List <System.Type> { tree.TableInfo.Type }; return(CheckRepeat(tree.Parent, types)); } return(types.Contains(tree.TableInfo.Type) || CheckRepeat(tree.Parent, types)); }
private static ISelect <T1> IncludeLevel <T1>(this ISelect <T1> select, int level, TableRefTree tree, ParameterExpression parameterExpression = null, MemberExpression bodyExpression = null) { var includeMethod = select.GetType().GetMethod("Include"); var includeManyMethod = select.GetType().GetMethod("IncludeMany"); parameterExpression ??= Expression.Parameter(tree.TableInfo.Type, "t"); foreach (var sub in tree.Subs) { switch (sub.TableRef.RefType) { case TableRefType.ManyToOne: case TableRefType.OneToOne: { var body = bodyExpression == null?Expression.Property(parameterExpression, sub.TableRef.Property) : Expression.Property(bodyExpression, sub.TableRef.Property); if (sub.Subs.Count == 0) { var funcType = typeof(Func <,>).MakeGenericType(parameterExpression.Type, sub.TableRef.RefEntityType); var navigateSelector = Expression.Lambda(funcType, body, parameterExpression); includeMethod.MakeGenericMethod(sub.TableRef.RefEntityType).Invoke(select, new object[] { navigateSelector }); } else { select.IncludeLevel(level, sub, parameterExpression, body); } } break; case TableRefType.ManyToMany: case TableRefType.OneToMany: { var body = bodyExpression == null?Expression.Property(parameterExpression, sub.TableRef.Property) : Expression.Property(bodyExpression, sub.TableRef.Property); object then = null; if (sub.Subs.Count > 0) { //var thenSelectType = select.GetType().GetGenericTypeDefinition().MakeGenericType(sub.TableRef.RefEntityType); var thenSelectType = typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType); var thenType = typeof(Action <>).MakeGenericType(thenSelectType); var thenParameter = Expression.Parameter(thenSelectType, "then"); var thenMethod = typeof(FreeSql_1113_Extensions).GetMethod(nameof(IncludeLevel)).MakeGenericMethod(sub.TableRef.RefEntityType); var thenLevelConst = Expression.Constant(level - sub.Level + 1); var thenBody = Expression.Call(null, thenMethod, thenParameter, thenLevelConst); var thenExpression = Expression.Lambda(thenType, thenBody, thenParameter); then = thenExpression.Compile(); } var funcType = typeof(Func <,>).MakeGenericType(parameterExpression.Type, typeof(IEnumerable <>).MakeGenericType(sub.TableRef.RefEntityType)); var navigateSelector = Expression.Lambda(funcType, body, parameterExpression); includeManyMethod.MakeGenericMethod(sub.TableRef.RefEntityType).Invoke(select, new object[] { navigateSelector, then }); } break; } } return(select); }
public static ISelect <T1> IncludeLevel <T1>(this ISelect <T1> select, int level) { var tree = TableRefTree.GetTableRefTree(select, level); return(select.IncludeLevel(level, tree)); }
private static Expression GetWhereExpression <T1>(ISelect <T1> select, TableRefTree deepest, DynamicFilterInfo filterInfo, string[] properties, Expression body, ref int manyLevel) { while (deepest.Parent != null && deepest.TableRef.RefType != TableRefType.ManyToMany && deepest.TableRef.RefType != TableRefType.OneToMany) { deepest = deepest.Parent; } manyLevel++; if (manyLevel == 1) { filterInfo = new DynamicFilterInfo { Field = string.Join(".", properties.Skip(deepest.Level - 1)), Operator = filterInfo.Operator, Value = filterInfo.Value, }; deepest = deepest.Parent; return(GetWhereExpression(select, deepest, filterInfo, properties, body, ref manyLevel)); } if (body == null) { body = Expression.Parameter(deepest.TableInfo.Type, $"t{deepest.Level}"); var sub = deepest; do { sub = sub.Subs.First(); body = Expression.Property(body, sub.TableRef.Property); } while (sub.TableRef.RefType != TableRefType.ManyToMany && sub.TableRef.RefType != TableRefType.OneToMany); var selectMethod = typeof(FreeSqlGlobalExtensions).GetMethods().First(a => a.Name == "AsSelect" && a.ContainsGenericParameters && a.GetParameters().Count() == 1).MakeGenericMethod(sub.TableRef.RefEntityType); body = Expression.Call(null, selectMethod, body); var asMethod = typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType).GetMethod("As"); var constExpression = Expression.Constant($"t{deepest.Level}"); body = Expression.Call(body, asMethod, constExpression); var whereDynamicFilterMethod = typeof(ISelect0 <,>).MakeGenericType(typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType), sub.TableRef.RefEntityType).GetMethod("WhereDynamicFilter"); body = Expression.Call(body, whereDynamicFilterMethod, Expression.Constant(filterInfo)); var anyMethod = typeof(ISelect0 <,>).MakeGenericType(typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType), sub.TableRef.RefEntityType).GetMethod("Any"); body = Expression.Call(body, anyMethod); deepest = deepest.Parent; } else { Expression subBody = Expression.Parameter(deepest.TableInfo.Type, $"t{deepest.Level}"); var sub = deepest; do { sub = sub.Subs.First(); subBody = Expression.Property(subBody, sub.TableRef.Property); } while (sub.TableRef.RefType != TableRefType.ManyToMany && sub.TableRef.RefType != TableRefType.OneToMany); var selectMethod = typeof(FreeSqlGlobalExtensions).GetMethods().First(a => a.Name == "AsSelect" && a.ContainsGenericParameters && a.GetParameters().Count() == 1).MakeGenericMethod(sub.TableRef.RefEntityType); subBody = Expression.Call(null, selectMethod, subBody); var anyMethod = typeof(ISelect <>).MakeGenericType(sub.TableRef.RefEntityType).GetMethod("Any"); var funcType = typeof(Func <,>).MakeGenericType(sub.TableRef.RefEntityType, typeof(bool)); var parameterBody = Expression.Parameter(sub.TableInfo.Type, $"t{sub.Level}"); var lambda = Expression.Lambda(funcType, body, parameterBody); body = Expression.Call(subBody, anyMethod, lambda); deepest = deepest.Parent; } if (deepest == null) { var funcType = typeof(Func <,>).MakeGenericType(typeof(T1), typeof(bool)); var parameterBody = Expression.Parameter(typeof(T1), "t1"); return(Expression.Lambda(funcType, body, parameterBody)); } else { return(GetWhereExpression(select, deepest, filterInfo, properties, body, ref manyLevel)); } }