OneToManyNavgateExpression.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace SqlSugar
  8. {
  9. internal class OneToManyNavgateExpression
  10. {
  11. private SqlSugarProvider context;
  12. private EntityInfo EntityInfo;
  13. private EntityInfo ProPertyEntity;
  14. private Navigate Navigat;
  15. public string ShorName;
  16. public string PropertyShortName;
  17. private string MemberName;
  18. private string MethodName;
  19. private string whereSql;
  20. public int ParameterIndex = 0;
  21. private MethodCallExpressionResolve methodCallExpressionResolve;
  22. public OneToManyNavgateExpression(SqlSugarProvider context, MethodCallExpressionResolve methodCallExpressionResolve)
  23. {
  24. this.context = context;
  25. this.methodCallExpressionResolve = methodCallExpressionResolve;
  26. }
  27. internal bool IsNavgate(Expression expression)
  28. {
  29. var result = false;
  30. var exp = expression;
  31. if (exp is UnaryExpression)
  32. {
  33. exp = (exp as UnaryExpression).Operand;
  34. }
  35. if (exp is MethodCallExpression)
  36. {
  37. var memberExp=exp as MethodCallExpression;
  38. MethodName = memberExp.Method.Name;
  39. if (memberExp.Method.Name.IsIn("Any","Count") && memberExp.Arguments.Count>0 && memberExp.Arguments[0] is MemberExpression )
  40. {
  41. result = ValidateNav(result, memberExp.Arguments[0] as MemberExpression, memberExp.Arguments[0]);
  42. if (memberExp.Arguments.Count > 1)
  43. {
  44. var pars = ExpressionTool.ExpressionParameters(memberExp.Arguments.Last());
  45. if (pars != null&& ProPertyEntity!=null&& pars.Any(z => z.Type == ProPertyEntity.Type))
  46. {
  47. PropertyShortName = pars.First(z => z.Type == ProPertyEntity.Type).Name;
  48. }
  49. whereSql = GetWhereSql(memberExp);
  50. }
  51. }
  52. }
  53. return result;
  54. }
  55. private string GetWhereSql(MethodCallExpression memberExp)
  56. {
  57. var whereExp = memberExp.Arguments[1];
  58. if (PropertyShortName.HasValue() && Navigat != null && Navigat.NavigatType == NavigateType.OneToMany)
  59. {
  60. InitType(whereExp);
  61. var result = this.methodCallExpressionResolve.GetNewExpressionValue(whereExp, ResolveExpressType.WhereMultiple);
  62. return result;
  63. }
  64. else if (whereExp!=null&&whereExp.Type == typeof(List<IConditionalModel>))
  65. {
  66. var value = ExpressionTool.GetExpressionValue(whereExp) as List<IConditionalModel>;
  67. //this.context.Utilities.Context.Queryable<object>().Where(value).ToList();
  68. if (value.HasValue())
  69. {
  70. var sqlbuilder = this.context.Queryable<object>().SqlBuilder;
  71. var sqlObj = sqlbuilder.ConditionalModelToSql(value, 0);
  72. var sql = sqlObj.Key;
  73. var count = methodCallExpressionResolve?.Context?.SugarContext?.QueryBuilder?.Parameters?.Count??0;
  74. UtilMethods.RepairReplicationParameters(ref sql, sqlObj.Value,0,"_"+ count+"_");
  75. methodCallExpressionResolve.Context.Parameters.AddRange(sqlObj.Value);
  76. return sql;
  77. }
  78. else
  79. {
  80. return " 1=1 ";
  81. }
  82. }
  83. else
  84. {
  85. InitType(whereExp);
  86. var result = this.methodCallExpressionResolve.GetNewExpressionValue(whereExp);
  87. return result;
  88. }
  89. }
  90. private void InitType(Expression whereExp)
  91. {
  92. if (whereExp is LambdaExpression)
  93. {
  94. var parameters = (whereExp as LambdaExpression).Parameters;
  95. if (parameters != null && parameters.Count > 0)
  96. {
  97. foreach (var item in parameters)
  98. {
  99. this.context.InitMappingInfo(item.Type);
  100. }
  101. }
  102. }
  103. }
  104. private bool ValidateNav(bool result, MemberExpression memberExp, Expression childExpression)
  105. {
  106. if (childExpression != null && childExpression is MemberExpression)
  107. {
  108. var child2Expression = (childExpression as MemberExpression).Expression;
  109. if (child2Expression.Type.IsClass() && child2Expression is ParameterExpression)
  110. {
  111. var rootType = child2Expression.Type;
  112. var rootEntity = this.context.EntityMaintenance.GetEntityInfo(rootType);
  113. var type= childExpression.Type.GetGenericArguments()[0];
  114. var entity = this.context.EntityMaintenance.GetEntityInfo(type);
  115. if (rootEntity.Columns.Any(x => x.PropertyName == (childExpression as MemberExpression).Member.Name && x.Navigat != null))
  116. {
  117. EntityInfo = rootEntity;
  118. ShorName = child2Expression.ToString();
  119. MemberName = memberExp.Member.Name;
  120. ProPertyEntity = entity;
  121. Navigat = rootEntity.Columns.FirstOrDefault(x => x.PropertyName == (childExpression as MemberExpression).Member.Name).Navigat;
  122. result = true;
  123. }
  124. }
  125. }
  126. return result;
  127. }
  128. internal MapperSql GetSql()
  129. {
  130. if (Navigat.NavigatType == NavigateType.OneToMany)
  131. {
  132. return GetOneToManySql();
  133. }
  134. else if (Navigat.NavigatType == NavigateType.Dynamic)
  135. {
  136. Check.ExceptionEasy(
  137. true,
  138. " NavigateType.Dynamic no support expression . " + this.ProPertyEntity.Type.Name,
  139. " NavigateType.Dynamic 自定义导航对象不支持在Where(x=>x.自定义.Id==1)等方法中使用" + this.ProPertyEntity.Type.Name);
  140. return null;
  141. }
  142. else
  143. {
  144. return GetManyToManySql();
  145. }
  146. }
  147. private MapperSql GetManyToManySql()
  148. {
  149. var bPk = this.ProPertyEntity.Columns.FirstOrDefault(it => it.IsPrimarykey == true)?.DbColumnName;
  150. var aPk = this.EntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey == true)?.DbColumnName;
  151. Check.ExceptionEasy(aPk.IsNullOrEmpty(), $"{this.EntityInfo.EntityName}need primary key", $"{this.EntityInfo.EntityName}需要主键");
  152. Check.ExceptionEasy(bPk.IsNullOrEmpty(), $"{this.ProPertyEntity.EntityName}need primary key", $"{this.ProPertyEntity.EntityName}需要主键");
  153. MapperSql mapper = new MapperSql();
  154. var queryable = this.context.Queryable<object>();
  155. bPk = queryable.QueryBuilder.Builder.GetTranslationColumnName(bPk);
  156. aPk = queryable.QueryBuilder.Builder.GetTranslationColumnName(aPk);
  157. var mappingType = Navigat.MappingType;
  158. Check.ExceptionEasy(mappingType == null, "ManyToMany misconfiguration", "多对多配置错误");
  159. var mappingEntity = this.context.EntityMaintenance.GetEntityInfo(mappingType);
  160. var mappingTableName=queryable.QueryBuilder.Builder.GetTranslationTableName(mappingEntity.DbTableName);
  161. var mappingA = mappingEntity.Columns.First(it => it.PropertyName == Navigat.MappingAId).DbColumnName;
  162. var mappingB = mappingEntity.Columns.First(it => it.PropertyName == Navigat.MappingBId).DbColumnName;
  163. mappingA = queryable.QueryBuilder.Builder.GetTranslationColumnName(mappingA);
  164. mappingB = queryable.QueryBuilder.Builder.GetTranslationColumnName(mappingB);
  165. var bTableName = queryable.QueryBuilder.Builder.GetTranslationTableName(this.ProPertyEntity.DbTableName);
  166. this.context.InitMappingInfo(mappingType);
  167. var queryBuilerAB=this.context.Queryable<object>().QueryBuilder;
  168. queryBuilerAB.LambdaExpressions.ParameterIndex = 100+this.ParameterIndex;
  169. var filters= queryBuilerAB.GetFilters(mappingType);
  170. if (filters.HasValue()&& this.methodCallExpressionResolve?.Context?.SugarContext?.QueryBuilder?.IsDisabledGobalFilter!=true)
  171. {
  172. aPk += " AND " + filters;
  173. if (queryBuilerAB.Parameters != null)
  174. {
  175. this.methodCallExpressionResolve.Context.Parameters.AddRange(queryBuilerAB.Parameters);
  176. }
  177. }
  178. mapper.Sql = $" (select {(MethodName == "Any" ? "1":" COUNT(1) ")} from {bTableName} {this.ProPertyEntity.DbTableName}_1 where {this.ProPertyEntity.DbTableName}_1.{bPk} in (select {mappingB} from {mappingTableName} where {mappingA} = {ShorName}.{aPk} ) )";
  179. if (this.whereSql.HasValue())
  180. {
  181. mapper.Sql = mapper.Sql.TrimEnd(')');
  182. if (this.whereSql.Contains($" {PropertyShortName}."))
  183. {
  184. this.whereSql = this.whereSql.Replace($" {PropertyShortName}.", $" {this.ProPertyEntity.DbTableName}_1.");
  185. }
  186. else if (this.whereSql.Contains($" {queryable.QueryBuilder.Builder.GetTranslationColumnName(PropertyShortName)}."))
  187. {
  188. this.whereSql = this.whereSql.Replace($" {queryable.QueryBuilder.Builder.GetTranslationColumnName(PropertyShortName)}.", $" {this.ProPertyEntity.DbTableName}_1.");
  189. }
  190. else if (this.whereSql.Contains($"({queryable.QueryBuilder.Builder.GetTranslationColumnName(PropertyShortName)}."))
  191. {
  192. this.whereSql = this.whereSql.Replace($"({queryable.QueryBuilder.Builder.GetTranslationColumnName(PropertyShortName)}.", $"({this.ProPertyEntity.DbTableName}_1.");
  193. }
  194. mapper.Sql = mapper.Sql + " AND " + this.whereSql+")";
  195. }
  196. if (MethodName == "Any")
  197. {
  198. mapper.Sql = $" {mapper.Sql} ";
  199. }
  200. else
  201. {
  202. mapper.Sql = $" ({mapper.Sql}) ";
  203. }
  204. mapper.Sql = GetMethodSql(mapper.Sql);
  205. return mapper;
  206. }
  207. private MapperSql GetOneToManySql()
  208. {
  209. var pkColumn = this.EntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey == true);
  210. if (Navigat.Name2.HasValue())
  211. {
  212. pkColumn = this.EntityInfo.Columns.FirstOrDefault(it => it.PropertyName== Navigat.Name2);
  213. }
  214. Check.ExceptionEasy(pkColumn == null, $"{this.EntityInfo.EntityName} need primary key ",
  215. $"导航属性 {this.EntityInfo.EntityName}需要主键");
  216. var pk = pkColumn.DbColumnName;
  217. var name = this.ProPertyEntity.Columns.First(it => it.PropertyName == Navigat.Name).DbColumnName;
  218. //var selectName = this.ProPertyEntity.Columns.First(it => it.PropertyName == MemberName).DbColumnName;
  219. MapperSql mapper = new MapperSql();
  220. var queryable = this.context.Queryable<object>();
  221. pk = queryable.QueryBuilder.Builder.GetTranslationColumnName(pk);
  222. name = queryable.QueryBuilder.Builder.GetTranslationColumnName(name);
  223. //selectName = queryable.QueryBuilder.Builder.GetTranslationColumnName(selectName);
  224. if (PropertyShortName.HasValue())
  225. {
  226. queryable.QueryBuilder.TableShortName = PropertyShortName;
  227. }
  228. queryable.QueryBuilder.LambdaExpressions.ParameterIndex = 500;
  229. var isClearFilter = false;
  230. Type[] clearTypes = null;
  231. if (this.methodCallExpressionResolve?.Context?.SugarContext?.QueryBuilder != null)
  232. {
  233. queryable.QueryBuilder.LambdaExpressions.ParameterIndex=500+ this.methodCallExpressionResolve.Context.SugarContext.QueryBuilder.LambdaExpressions.ParameterIndex;
  234. this.methodCallExpressionResolve.Context.SugarContext.QueryBuilder.LambdaExpressions.ParameterIndex++;
  235. isClearFilter=this.methodCallExpressionResolve.Context.SugarContext.QueryBuilder.IsDisabledGobalFilter;
  236. clearTypes = this.methodCallExpressionResolve.Context.SugarContext.QueryBuilder.RemoveFilters;
  237. }
  238. var sqlObj = queryable
  239. .AS(this.ProPertyEntity.DbTableName)
  240. .ClearFilter(clearTypes)
  241. .Filter(isClearFilter?null:this.ProPertyEntity.Type)
  242. .WhereIF(!string.IsNullOrEmpty(whereSql), whereSql)
  243. .Where($" {name}={queryable.QueryBuilder.Builder.GetTranslationColumnName( ShorName)}.{pk} ").Select(MethodName == "Any" ? "1" : " COUNT(1) ").ToSql();
  244. if (sqlObj.Value?.Any() == true)
  245. {
  246. foreach (var item in sqlObj.Value)
  247. {
  248. if (!this.methodCallExpressionResolve.Context.Parameters.Any(it => it.ParameterName == item.ParameterName))
  249. {
  250. this.methodCallExpressionResolve.Context.Parameters.Add(item);
  251. }
  252. }
  253. }
  254. mapper.Sql = sqlObj.Key;
  255. mapper.Sql = $" ({mapper.Sql}) ";
  256. mapper.Sql = GetMethodSql(mapper.Sql);
  257. return mapper;
  258. }
  259. private string GetMethodSql(string sql)
  260. {
  261. if (MethodName == "Any")
  262. {
  263. return $" ( EXISTS {sql} ) ";
  264. }
  265. return sql;
  266. }
  267. }
  268. }