OneToManyNavgateExpressionN.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using System.Threading.Tasks;
  8. namespace SqlSugar
  9. {
  10. internal class OneToManyNavgateExpressionN
  11. {
  12. #region Constructor
  13. public SqlSugarProvider context;
  14. public string shorName;
  15. public EntityInfo entityInfo;
  16. public List<ExpressionItems> items;
  17. public string whereSql;
  18. public MethodCallExpressionResolve methodCallExpressionResolve;
  19. public OneToManyNavgateExpressionN(SqlSugarProvider context, MethodCallExpressionResolve methodCallExpressionResolve)
  20. {
  21. this.context = context;
  22. this.methodCallExpressionResolve= methodCallExpressionResolve;
  23. }
  24. #endregion
  25. internal bool IsNavgate(Expression expression)
  26. {
  27. var result = false;
  28. var exp = expression;
  29. if (exp is UnaryExpression)
  30. {
  31. exp = (exp as UnaryExpression).Operand;
  32. }
  33. if (exp is MethodCallExpression)
  34. {
  35. var memberExp=exp as MethodCallExpression;
  36. if (memberExp.Method.Name.IsIn("Any","Count") && memberExp.Arguments.Count>0 && memberExp.Arguments[0] is MemberExpression )
  37. {
  38. result = ValiteOneManyCall(result, memberExp, memberExp.Arguments[0] as MemberExpression, memberExp.Arguments[0]);
  39. if (memberExp.Arguments.Count > 1)
  40. {
  41. whereSql = GetWhereSql(memberExp);
  42. }
  43. }
  44. }
  45. return result;
  46. }
  47. private bool ValiteOneManyCall(bool result,MethodCallExpression callExpression, MemberExpression memberExp, Expression childExpression)
  48. {
  49. if (childExpression != null && childExpression is MemberExpression)
  50. {
  51. var oldChildExpression = childExpression;
  52. var child2Expression = (childExpression as MemberExpression).Expression;
  53. if (child2Expression == null || (child2Expression is ConstantExpression))
  54. {
  55. return false;
  56. }
  57. items = new List<ExpressionItems>();
  58. var childType = oldChildExpression.Type;
  59. if (!childType.FullName.IsCollectionsList())
  60. {
  61. return false;
  62. }
  63. childType = childType.GetGenericArguments()[0];
  64. items.Add(new ExpressionItems() { Type = 3, Expression = callExpression, ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(childType) });
  65. items.Add(new ExpressionItems() { Type = 2, Expression = oldChildExpression, ThisEntityInfo = this.context.EntityMaintenance.GetEntityInfo(childType), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type) });
  66. if (items.Any(it => it.Type == 2 && it.Nav == null))
  67. {
  68. return false;
  69. }
  70. while (child2Expression != null)
  71. {
  72. if (IsClass(child2Expression))
  73. {
  74. items.Add(new ExpressionItems() { Type = 2, Expression = child2Expression, ThisEntityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type), ParentEntityInfo = this.context.EntityMaintenance.GetEntityInfo(GetMemberExpression(child2Expression).Type) });
  75. child2Expression = GetMemberExpression(child2Expression);
  76. }
  77. else if (IsParameter(child2Expression))
  78. {
  79. shorName = child2Expression.ToString();
  80. entityInfo = this.context.EntityMaintenance.GetEntityInfo(child2Expression.Type);
  81. break;
  82. }
  83. else
  84. {
  85. break;
  86. }
  87. }
  88. if (!items.Any(it => it.Type == 2 && it.Nav == null))
  89. {
  90. return true;
  91. }
  92. }
  93. return result;
  94. }
  95. public object GetSql()
  96. {
  97. MapperSql MapperSql = new MapperSql();
  98. var memberInfo = this.items.Where(it => it.Type == 3).First();
  99. var subInfos = this.items.Where(it => it.Type == 2).Reverse().ToList();
  100. var formInfo = subInfos.First();
  101. var joinInfos = subInfos.Skip(1).ToList();
  102. var i = 0;
  103. var masterShortName = formInfo.ThisEntityInfo.DbTableName + i;
  104. var queryable = this.context.Queryable<object>(masterShortName).AS(formInfo.ThisEntityInfo.DbTableName);
  105. i++;
  106. var lastShortName = "";
  107. var index = 0;
  108. foreach (var item in joinInfos)
  109. {
  110. if (item.Nav.NavigatType == NavigateType.OneToMany)
  111. {
  112. lastShortName = OneToMany(ref formInfo, ref i, queryable, ref index, item);
  113. }
  114. else if (item.Nav.NavigatType == NavigateType.OneToOne)
  115. {
  116. lastShortName = OneToOne(ref formInfo, ref i, queryable, ref index, item);
  117. }
  118. else
  119. {
  120. lastShortName = ManyToMany(ref formInfo, ref i, queryable, ref index, item);
  121. }
  122. }
  123. var isAny = (memberInfo.Expression as MethodCallExpression).Method.Name == "Any";
  124. queryable.Select(isAny ? "1" : " COUNT(1) ");
  125. var last = subInfos.First();
  126. var FirstPkColumn = last.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  127. FirstPkColumn = GetFirstPkColumn(last, FirstPkColumn);
  128. Check.ExceptionEasy(FirstPkColumn == null, $"{ last.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{ last.ThisEntityInfo.EntityName} 缺少主键");
  129. var PkColumn = last.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == last.Nav.Name);
  130. Check.ExceptionEasy(PkColumn == null, $"{ last.ParentEntityInfo.EntityName} no found {last.Nav.Name}", $"{ last.ParentEntityInfo.EntityName} 不存在 {last.Nav.Name}");
  131. queryable.Where($" {this.shorName}.{ queryable.SqlBuilder.GetTranslationColumnName(PkColumn.DbColumnName)} = {masterShortName}.{queryable.SqlBuilder.GetTranslationColumnName(FirstPkColumn.DbColumnName)} ");
  132. queryable.WhereIF(this.whereSql.HasValue(), GetWhereSql1(this.whereSql,lastShortName, joinInfos, queryable.SqlBuilder));
  133. MapperSql.Sql = $"( {queryable.ToSql().Key} ) ";
  134. if (isAny)
  135. {
  136. MapperSql.Sql = $" EXISTS( {MapperSql.Sql}) ";
  137. }
  138. return MapperSql;
  139. }
  140. private static EntityColumnInfo GetFirstPkColumn(ExpressionItems last, EntityColumnInfo FirstPkColumn)
  141. {
  142. if (last.Nav.NavigatType == NavigateType.OneToOne && last.Nav.Name2.HasValue())
  143. {
  144. var name2 = last.ThisEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == last.Nav.Name2);
  145. if (name2 != null)
  146. {
  147. FirstPkColumn = name2;
  148. }
  149. }
  150. return FirstPkColumn;
  151. }
  152. private static string OneToMany(ref ExpressionItems formInfo, ref int i, ISugarQueryable<object> queryable, ref int index, ExpressionItems item)
  153. {
  154. string lastShortName;
  155. var shortName = item.ThisEntityInfo.DbTableName + i;
  156. EntityColumnInfo pkColumn;
  157. EntityColumnInfo navColum;
  158. //if (index == 0)
  159. //{
  160. pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name);
  161. navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  162. if (item.Nav.Name2.HasValue())
  163. {
  164. navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name2);
  165. }
  166. //}
  167. //else
  168. //{
  169. // pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  170. // navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name);
  171. //}
  172. Check.ExceptionEasy(pkColumn == null, $"{item.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{item.ThisEntityInfo.EntityName} 缺少主键");
  173. var on = $" {shortName}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}";
  174. queryable.AddJoinInfo(item.ThisEntityInfo.DbTableName, shortName, on, JoinType.Inner);
  175. ++i;
  176. index++;
  177. lastShortName = shortName;
  178. formInfo = item;
  179. return lastShortName;
  180. }
  181. private static string OneToOne(ref ExpressionItems formInfo, ref int i, ISugarQueryable<object> queryable, ref int index, ExpressionItems item)
  182. {
  183. string lastShortName;
  184. var shortName = item.ThisEntityInfo.DbTableName + i;
  185. EntityColumnInfo pkColumn;
  186. EntityColumnInfo navColum;
  187. //if (index == 0)
  188. //{
  189. // pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name);
  190. // navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  191. //}
  192. //else
  193. //{
  194. pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it =>it.IsPrimarykey );
  195. navColum = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name);
  196. if (item.Nav.Name2.HasValue())
  197. {
  198. pkColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.PropertyName == item.Nav.Name2);
  199. }
  200. //}
  201. Check.ExceptionEasy(pkColumn == null, $"{item.ThisEntityInfo.EntityName} need PrimayKey", $"使用导航属性{item.ThisEntityInfo.EntityName} 缺少主键");
  202. var on = $" {shortName}.{queryable.SqlBuilder.GetTranslationColumnName(pkColumn.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(navColum.DbColumnName)}";
  203. queryable.AddJoinInfo(item.ThisEntityInfo.DbTableName, shortName, on, JoinType.Inner);
  204. ++i;
  205. index++;
  206. lastShortName = shortName;
  207. formInfo = item;
  208. return lastShortName;
  209. }
  210. private string ManyToMany(ref ExpressionItems formInfo, ref int i, ISugarQueryable<object> queryable, ref int index, ExpressionItems item)
  211. {
  212. string lastShortName;
  213. var bshortName = item.ThisEntityInfo.DbTableName + i;
  214. EntityColumnInfo AidColumn;
  215. EntityColumnInfo BidColumn;
  216. BidColumn = item.ThisEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  217. AidColumn = item.ParentEntityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey);
  218. var abEntity =this.context.EntityMaintenance.GetEntityInfo(item.Nav.MappingType);
  219. var Ab_Aid = abEntity.Columns.FirstOrDefault(it => item.Nav.MappingAId == it.PropertyName);
  220. var Ab_Bid = abEntity.Columns.FirstOrDefault(it => item.Nav.MappingBId == it.PropertyName);
  221. Check.ExceptionEasy(AidColumn == null, $" {AidColumn.EntityName} need primary key ", $"{AidColumn.EntityName}需要主键");
  222. Check.ExceptionEasy(AidColumn == null, $" {BidColumn.EntityName} need primary key ", $"{BidColumn.EntityName}需要主键");
  223. var abShort = abEntity.EntityName + "_1";
  224. var abOn = $" {abShort}.{queryable.SqlBuilder.GetTranslationColumnName(Ab_Aid.DbColumnName)}={formInfo.ThisEntityInfo.DbTableName + (i - 1)}.{queryable.SqlBuilder.GetTranslationColumnName(AidColumn.DbColumnName)}";
  225. queryable.AddJoinInfo(abEntity.DbTableName, abShort, abOn, JoinType.Inner);
  226. var On = $" {bshortName}.{queryable.SqlBuilder.GetTranslationColumnName(BidColumn.DbColumnName)}={abShort}.{queryable.SqlBuilder.GetTranslationColumnName(Ab_Bid.DbColumnName)}";
  227. queryable.AddJoinInfo(BidColumn.DbTableName, bshortName, On, JoinType.Inner);
  228. ++i;
  229. index++;
  230. lastShortName = bshortName;
  231. formInfo = item;
  232. return lastShortName;
  233. }
  234. #region Helper
  235. private string GetWhereSql1(string wheresql,string lastShortName, List<ExpressionItems> joinInfos,ISqlBuilder sqlBuilder)
  236. {
  237. var sql = wheresql;
  238. if (sql == null) return sql;
  239. joinInfos.Last().ThisEntityInfo.Columns.ForEach(it =>
  240. {
  241. if (it.DbColumnName != null)
  242. {
  243. if (this.whereSql.Contains("." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)))
  244. {
  245. var regex = @"\w+\." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)
  246. .Replace(sqlBuilder.SqlTranslationLeft, "\\" + sqlBuilder.SqlTranslationLeft)
  247. .Replace(sqlBuilder.SqlTranslationRight, "\\" + sqlBuilder.SqlTranslationRight)
  248. .Replace("\\\\","\\");
  249. if (!regex.IsMatch(this.whereSql))
  250. {
  251. regex = $@"\{sqlBuilder.SqlTranslationLeft}\w+\{sqlBuilder.SqlTranslationRight}\." + sqlBuilder.GetTranslationColumnName(it.DbColumnName)
  252. .Replace(sqlBuilder.SqlTranslationLeft, "\\" + sqlBuilder.SqlTranslationLeft)
  253. .Replace(sqlBuilder.SqlTranslationRight, "\\" + sqlBuilder.SqlTranslationRight)
  254. .Replace("\\\\", "\\");
  255. }
  256. this.whereSql =Regex.Replace(this.whereSql, regex,
  257. lastShortName + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName));
  258. }
  259. else
  260. {
  261. var oldWhere = this.whereSql;
  262. var newWhere = this.whereSql.Replace(sqlBuilder.GetTranslationColumnName(it.DbColumnName),
  263. lastShortName + "." + sqlBuilder.GetTranslationColumnName(it.DbColumnName));
  264. if (oldWhere != newWhere && !oldWhere.Contains($" {sqlBuilder.GetTranslationColumnName(it.DbColumnName)}"))
  265. {
  266. }
  267. else
  268. {
  269. this.whereSql = newWhere;
  270. }
  271. }
  272. }
  273. });
  274. return this.whereSql;
  275. }
  276. private string GetWhereSql(MethodCallExpression memberExp)
  277. {
  278. var whereExp = memberExp.Arguments[1];
  279. var result = this.methodCallExpressionResolve.GetNewExpressionValue(whereExp);
  280. return result;
  281. }
  282. private static bool IsParameter(Expression child2Expression)
  283. {
  284. return child2Expression.Type.IsClass() && child2Expression is ParameterExpression;
  285. }
  286. private static Expression GetMemberExpression(Expression child2Expression)
  287. {
  288. return (child2Expression as MemberExpression).Expression;
  289. }
  290. private static bool IsClass(Expression child2Expression)
  291. {
  292. return child2Expression.Type.IsClass() && child2Expression is MemberExpression;
  293. }
  294. #endregion
  295. }
  296. }