QueryBuilder.cs 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134
  1. using NetTaste;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Dynamic;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Text.RegularExpressions;
  10. namespace SqlSugar
  11. {
  12. public abstract class QueryBuilder : IDMLBuilder
  13. {
  14. public QueryBuilder()
  15. {
  16. this.Parameters = new List<SugarParameter>();
  17. }
  18. #region Private Fileds
  19. protected List<JoinQueryInfo> _JoinQueryInfos;
  20. protected Dictionary<string, string> _EasyJoinInfos;
  21. private List<string> _WhereInfos;
  22. private string _HavingInfos;
  23. protected string _TableNameString;
  24. #endregion
  25. #region Service object
  26. public StringBuilder sql { get; set; }
  27. public SqlSugarProvider Context { get; set; }
  28. public ILambdaExpressions LambdaExpressions { get; set; }
  29. public ISqlBuilder Builder { get; set; }
  30. #endregion
  31. #region Splicing basic
  32. public string Hints { get; set; }
  33. internal AppendNavInfo AppendNavInfo { get; set; }
  34. public Type[] RemoveFilters { get; set; }
  35. public Dictionary<string, object> SubToListParameters { get; set; }
  36. internal List<QueryableAppendColumn> AppendColumns { get; set; }
  37. internal List<List<QueryableAppendColumn>> AppendValues { get; set; }
  38. public bool IsCrossQueryWithAttr { get; set; }
  39. public Dictionary<string,string> CrossQueryItems { get; set; }
  40. public bool IsSelectSingleFiledJson { get; set; }
  41. public bool IsSelectSingleFiledArray { get; set; }
  42. public string TranLock { get; set; }
  43. public bool IsDisableMasterSlaveSeparation { get; set; }
  44. public bool IsEnableMasterSlaveSeparation { get; set; }
  45. public bool IsQueryInQuery { get; set; }
  46. public List<object> Includes { get; set; }
  47. public List<string> IgnoreColumns { get; set; }
  48. public bool IsCount { get; set; }
  49. public bool IsSqlQuery { get; set; }
  50. public bool IsSqlQuerySelect { get; set; }
  51. public int? Skip { get; set; }
  52. public int ExternalPageIndex { get; set; }
  53. public int ExternalPageSize { get; set; }
  54. public int? Take { get; set; }
  55. public bool DisableTop { get; set; }
  56. public string SampleBy { get; set; }
  57. public string OrderByValue { get; set; }
  58. public object SelectValue { get; set; }
  59. public string SelectCacheKey { get; set; }
  60. public string EntityName { get; set; }
  61. public string OldSql { get; set; }
  62. public Type EntityType { get; set; }
  63. public Type ResultType { get; set; }
  64. public string TableWithString { get; set; }
  65. public string GroupByValue { get; set; }
  66. public string PartitionByValue { get; set; }
  67. public int WhereIndex { get; set; }
  68. public bool IsDistinct { get; set; }
  69. public int JoinIndex { get; set; }
  70. public bool IsDisabledGobalFilter { get; set; }
  71. public virtual List<SugarParameter> Parameters { get; set; }
  72. public Expression JoinExpression { get; set; }
  73. public Dictionary<string, string> EasyJoinInfos
  74. {
  75. get
  76. {
  77. _EasyJoinInfos = UtilMethods.IsNullReturnNew(_EasyJoinInfos);
  78. return _EasyJoinInfos;
  79. }
  80. set { _EasyJoinInfos = value; }
  81. }
  82. public virtual List<JoinQueryInfo> JoinQueryInfos
  83. {
  84. get
  85. {
  86. _JoinQueryInfos = UtilMethods.IsNullReturnNew(_JoinQueryInfos);
  87. return _JoinQueryInfos;
  88. }
  89. set { _JoinQueryInfos = value; }
  90. }
  91. public virtual string TableShortName { get; set; }
  92. public virtual List<string> WhereInfos
  93. {
  94. get
  95. {
  96. _WhereInfos = UtilMethods.IsNullReturnNew(_WhereInfos);
  97. return _WhereInfos;
  98. }
  99. set { _WhereInfos = value; }
  100. }
  101. public virtual string HavingInfos
  102. {
  103. get
  104. {
  105. return _HavingInfos;
  106. }
  107. set
  108. {
  109. _HavingInfos = value;
  110. }
  111. }
  112. #endregion
  113. #region Lambada Type
  114. public ResolveExpressType SelectType
  115. {
  116. get
  117. {
  118. return this.IsSingle() ? ResolveExpressType.SelectSingle : ResolveExpressType.SelectMultiple;
  119. }
  120. }
  121. public ResolveExpressType WheretType
  122. {
  123. get
  124. {
  125. return this.IsSingle() ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple;
  126. }
  127. }
  128. #endregion
  129. #region Sql Template
  130. public Dictionary<string, string> AsTables=new Dictionary<string, string>();
  131. public virtual string SqlTemplate
  132. {
  133. get
  134. {
  135. if (this.SampleBy.HasValue())
  136. {
  137. return "SELECT {0} FROM {1}{2} "+ this.SampleBy + " {3}{4}";
  138. }
  139. return "SELECT {0} FROM {1}{2}{3}{4} ";
  140. }
  141. }
  142. public virtual string JoinTemplate
  143. {
  144. get
  145. {
  146. return "{0}JOIN {1}{2}ON {3} ";
  147. }
  148. }
  149. public virtual string PageTempalte
  150. {
  151. get
  152. {
  153. return @"SELECT * FROM ({0}) T WHERE RowIndex BETWEEN {1} AND {2}";
  154. }
  155. }
  156. public virtual string ExternalPageTempalte
  157. {
  158. get
  159. {
  160. return @"SELECT * FROM ({0}) T WHERE RowIndex2 BETWEEN {1} AND {2}";
  161. }
  162. }
  163. public virtual string DefaultOrderByTemplate
  164. {
  165. get
  166. {
  167. return "ORDER BY " + this.Builder.SqlDateNow + " ";
  168. }
  169. }
  170. public virtual string OrderByTemplate
  171. {
  172. get
  173. {
  174. return "ORDER BY ";
  175. }
  176. }
  177. public virtual string GroupByTemplate
  178. {
  179. get
  180. {
  181. return "GROUP BY ";
  182. }
  183. }
  184. public virtual string PartitionByTemplate
  185. {
  186. get
  187. {
  188. return "PARTITION BY ";
  189. }
  190. }
  191. public virtual string MaxTemplate
  192. {
  193. get
  194. {
  195. return "MAX({0})";
  196. }
  197. }
  198. public virtual string MinTemplate
  199. {
  200. get
  201. {
  202. return "MIN({0})";
  203. }
  204. }
  205. public virtual string SumTemplate
  206. {
  207. get
  208. {
  209. return "SUM({0})";
  210. }
  211. }
  212. public virtual string AvgTemplate
  213. {
  214. get
  215. {
  216. return "AVG({0})";
  217. }
  218. }
  219. public virtual string InTemplate
  220. {
  221. get
  222. {
  223. return "{0} IN ({1}) ";
  224. }
  225. }
  226. public virtual string EqualTemplate
  227. {
  228. get
  229. {
  230. return "{0} = {1} ";
  231. }
  232. }
  233. #endregion
  234. #region Common Methods
  235. public virtual bool IsSingle()
  236. {
  237. var isSingle = Builder.QueryBuilder.JoinQueryInfos.IsNullOrEmpty() && !EasyJoinInfos.Any();
  238. return isSingle;
  239. }
  240. public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType)
  241. {
  242. ILambdaExpressions resolveExpress = this.LambdaExpressions;
  243. if (resolveType.IsIn(ResolveExpressType.FieldSingle, ResolveExpressType.FieldMultiple, ResolveExpressType.SelectSingle, ResolveExpressType.SelectMultiple) && (expression is LambdaExpression) && (expression as LambdaExpression).Body is BinaryExpression)
  244. {
  245. resolveType = resolveType.IsIn(ResolveExpressType.SelectSingle, ResolveExpressType.FieldSingle) ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple;
  246. }
  247. this.LambdaExpressions.Clear();
  248. if (this.Context.CurrentConnectionConfig.MoreSettings != null)
  249. {
  250. resolveExpress.TableEnumIsString = this.Context.CurrentConnectionConfig.MoreSettings.TableEnumIsString;
  251. resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
  252. }
  253. else
  254. {
  255. resolveExpress.PgSqlIsAutoToLower = true;
  256. }
  257. resolveExpress.SugarContext = new ExpressionOutParameter() { Context = this.Context, QueryBuilder = this } ;
  258. resolveExpress.RootExpression = expression;
  259. resolveExpress.JoinQueryInfos = Builder.QueryBuilder.JoinQueryInfos;
  260. resolveExpress.IsSingle = IsSingle()&& resolveType!= ResolveExpressType.WhereMultiple;
  261. resolveExpress.MappingColumns = Context.MappingColumns;
  262. resolveExpress.MappingTables = Context.MappingTables;
  263. resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
  264. resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
  265. resolveExpress.InitMappingInfo = this.Context.InitMappingInfo;
  266. resolveExpress.RefreshMapping = () =>
  267. {
  268. resolveExpress.MappingColumns = Context.MappingColumns;
  269. resolveExpress.MappingTables = Context.MappingTables;
  270. resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
  271. resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
  272. };
  273. resolveExpress.Resolve(expression, resolveType);
  274. this.Parameters.AddRange(resolveExpress.Parameters.Select(it => new SugarParameter(it.ParameterName, it.Value, it.DbType) { Size=it.Size,TypeName=it.TypeName, IsNvarchar2=it.IsNvarchar2}));
  275. var result = resolveExpress.Result;
  276. var isSingleTableHasSubquery = IsSingle() && resolveExpress.SingleTableNameSubqueryShortName.HasValue();
  277. if (isSingleTableHasSubquery)
  278. {
  279. if (this.TableShortName != null && this.TableShortName.StartsWith("\""))
  280. {
  281. Check.Exception(!string.IsNullOrEmpty(this.TableShortName) && resolveExpress.SingleTableNameSubqueryShortName != this.TableShortName.TrimEnd('\"').TrimStart('\"'), "{0} and {1} need same name", resolveExpress.SingleTableNameSubqueryShortName, this.TableShortName);
  282. this.TableShortName = resolveExpress.SingleTableNameSubqueryShortName;
  283. }
  284. else
  285. {
  286. Check.Exception(!string.IsNullOrEmpty(this.TableShortName) && resolveExpress.SingleTableNameSubqueryShortName != this.TableShortName, "{0} and {1} need same name", resolveExpress.SingleTableNameSubqueryShortName, this.TableShortName);
  287. this.TableShortName = resolveExpress.SingleTableNameSubqueryShortName;
  288. }
  289. }
  290. return result;
  291. }
  292. internal string GetFilters(Type type)
  293. {
  294. var result = "";
  295. if (this.Context != null)
  296. {
  297. var db = Context;
  298. BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public;
  299. var index = 0;
  300. if (db.QueryFilter.GeFilterList != null)
  301. {
  302. foreach (var item in db.QueryFilter.GeFilterList)
  303. {
  304. if (this.RemoveFilters != null && this.RemoveFilters.Length > 0)
  305. {
  306. if (this.RemoveFilters.Contains(item.type))
  307. {
  308. continue;
  309. }
  310. }
  311. PropertyInfo field = item.GetType().GetProperty("exp", flag);
  312. if (field != null)
  313. {
  314. Type ChildType = item.type;
  315. var isInterface = ChildType.IsInterface && type.GetInterfaces().Any(it => it == ChildType);
  316. if (ChildType == type|| isInterface)
  317. {
  318. var entityInfo = db.EntityMaintenance.GetEntityInfo(ChildType);
  319. var exp = field.GetValue(item, null) as Expression;
  320. var whereStr = index==0 ? " " : " AND ";
  321. index++;
  322. result += (whereStr + GetExpressionValue(exp, ResolveExpressType.WhereSingle).GetString());
  323. if (isInterface)
  324. {
  325. result = ReplaceFilterColumnName(result,type);
  326. }
  327. }
  328. }
  329. }
  330. }
  331. }
  332. return result;
  333. }
  334. public virtual string ToSqlString()
  335. {
  336. string oldOrderBy = this.OrderByValue;
  337. string externalOrderBy = oldOrderBy;
  338. var isIgnoreOrderBy = this.IsCount && this.PartitionByValue.IsNullOrEmpty();
  339. AppendFilter();
  340. sql = new StringBuilder();
  341. if (this.OrderByValue == null && (Skip != null || Take != null)) this.OrderByValue = " ORDER BY GetDate() ";
  342. if (this.PartitionByValue.HasValue())
  343. {
  344. this.OrderByValue = this.PartitionByValue + this.OrderByValue;
  345. }
  346. var isRowNumber = Skip != null || Take != null;
  347. var rowNumberString = string.Format(",ROW_NUMBER() OVER({0}) AS RowIndex ", GetOrderByString);
  348. string groupByValue = GetGroupByString + HavingInfos;
  349. string orderByValue = (!isRowNumber && this.OrderByValue.HasValue()) ? GetOrderByString : null;
  350. if (isIgnoreOrderBy) { orderByValue = null; }
  351. sql.AppendFormat(SqlTemplate, GetSelectValue, GetTableNameString, GetWhereValueString, groupByValue, orderByValue);
  352. sql.Replace(UtilConstants.ReplaceKey, isRowNumber ? (isIgnoreOrderBy ? null : rowNumberString) : null);
  353. if (isIgnoreOrderBy) { this.OrderByValue = oldOrderBy; return sql.ToString(); }
  354. var result = ToPageSql(sql.ToString(), this.Take, this.Skip);
  355. if (ExternalPageIndex > 0)
  356. {
  357. if (externalOrderBy.IsNullOrEmpty())
  358. {
  359. externalOrderBy = " ORDER BY GetDate() ";
  360. }
  361. result = string.Format("SELECT *,ROW_NUMBER() OVER({0}) AS RowIndex2 FROM ({1}) ExternalTable ", GetExternalOrderBy(externalOrderBy), result);
  362. result = ToPageSql2(result, ExternalPageIndex, ExternalPageSize, true);
  363. }
  364. this.OrderByValue = oldOrderBy;
  365. return result;
  366. }
  367. public virtual void AppendFilter()
  368. {
  369. if (!IsDisabledGobalFilter && this.Context.QueryFilter.GeFilterList.HasValue())
  370. {
  371. var gobalFilterList = this.Context.QueryFilter.GeFilterList.Where(it => it.FilterName.IsNullOrEmpty()).ToList();
  372. if (this.RemoveFilters != null && this.RemoveFilters.Length > 0)
  373. {
  374. gobalFilterList = gobalFilterList.Where(it => !this.RemoveFilters.Contains(it.type)).ToList();
  375. }
  376. foreach (var item in gobalFilterList)
  377. {
  378. if (item.GetType().Name.StartsWith("TableFilterItem"))
  379. {
  380. AppendTableFilter(item);
  381. }
  382. }
  383. foreach (var item in gobalFilterList.Where(it=>it.GetType().Name=="SqlFilterItem").Where(it => it.IsJoinQuery == !IsSingle()))
  384. {
  385. var filterResult = item.FilterValue(this.Context);
  386. WhereInfos.Add(this.Builder.AppendWhereOrAnd(this.WhereInfos.IsNullOrEmpty(), filterResult.Sql + UtilConstants.Space));
  387. var filterParamters = this.Context.Ado.GetParameters(filterResult.Parameters);
  388. if (filterParamters.HasValue())
  389. {
  390. this.Parameters.AddRange(filterParamters);
  391. }
  392. }
  393. }
  394. }
  395. private void AppendTableFilter(SqlFilterItem item)
  396. {
  397. BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic |BindingFlags.Public;
  398. Type type = item.GetType();
  399. PropertyInfo field = type.GetProperty("exp", flag);
  400. Type ChildType = item.type;
  401. var entityInfo = this.Context.EntityMaintenance.GetEntityInfoWithAttr(ChildType);
  402. var exp = field.GetValue(item, null) as Expression;
  403. var isMain = ChildType == this.EntityType||(ChildType.IsInterface&& this.EntityType.GetInterfaces().Any(it => it == ChildType));
  404. var isSingle = IsSingle();
  405. var itName = (exp as LambdaExpression).Parameters[0].Name;
  406. itName = this.Builder.GetTranslationColumnName(itName) + ".";
  407. var isEasyJoin = this.EasyJoinInfos.Count > 0;
  408. string sql = "";
  409. if (isSingle)
  410. {
  411. if (ChildType.IsInterface&&this.EntityType.GetInterfaces().Any(it => it == ChildType))
  412. {
  413. //future
  414. }
  415. else if (ChildType != this.EntityType && isSingle)
  416. {
  417. return;
  418. }
  419. sql = GetSql(exp, isSingle);
  420. if (ChildType.IsInterface)
  421. {
  422. var filterType = this.EntityType;
  423. sql = ReplaceFilterColumnName(sql, filterType);
  424. }
  425. }
  426. else if (isEasyJoin && ChildType.IsInterface && this.JoinExpression != null && (this.JoinExpression as LambdaExpression)?.Parameters?.Any(it => it.Type.GetInterfaces().Any(z => z == ChildType)) == true)
  427. {
  428. var parameters = (this.JoinExpression as LambdaExpression).Parameters.Where(it => it.Type.GetInterfaces().Any(z => z == ChildType)).ToList();
  429. foreach (var parameter in parameters)
  430. {
  431. var shortName = this.Builder.GetTranslationColumnName(parameter.Name) + ".";
  432. var mysql = GetSql(exp, isSingle);
  433. sql += mysql.Replace(itName, shortName);
  434. var filterType =parameter.Type;
  435. sql = ReplaceFilterColumnName(sql, filterType);
  436. }
  437. }
  438. else if (isMain)
  439. {
  440. if (TableShortName == null)
  441. return;
  442. var isSameName =!isSingle&& this.JoinQueryInfos.Count(it => it.TableName == entityInfo.DbTableName)>0;
  443. if (isSameName||ChildType.IsInterface)
  444. {
  445. var mysql = GetSql(exp, isSingle);
  446. if (ChildType.IsInterface)
  447. {
  448. foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.EntityType.GetInterfaces().Any(z=>z==ChildType)))
  449. {
  450. var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(joinInfoItem.ShortName) + ".");
  451. addSql = ReplaceFilterColumnName(addSql, joinInfoItem.EntityType,joinInfoItem.ShortName);
  452. joinInfoItem.JoinWhere += (" AND " + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
  453. }
  454. }
  455. else
  456. {
  457. foreach (var joinInfoItem in this.JoinQueryInfos.Where(it => it.TableName == entityInfo.DbTableName))
  458. {
  459. var addSql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(joinInfoItem.ShortName) + ".");
  460. addSql = ReplaceFilterColumnName(addSql, joinInfoItem.EntityType, joinInfoItem.ShortName);
  461. joinInfoItem.JoinWhere += (" AND " + Regex.Replace(addSql, "^ (WHERE|AND) ", ""));
  462. }
  463. }
  464. sql = mysql.Replace(itName, this.Builder.GetTranslationColumnName(TableShortName) + ".");
  465. }
  466. else
  467. {
  468. var shortName = this.Builder.GetTranslationColumnName(TableShortName) + ".";
  469. sql = GetSql(exp, isSingle);
  470. sql = sql.Replace(itName, shortName);
  471. }
  472. if (ChildType.IsInterface)
  473. {
  474. sql = ReplaceFilterColumnName(sql, this.EntityType);
  475. }
  476. }
  477. else if (isEasyJoin)
  478. {
  479. var easyInfo = EasyJoinInfos.FirstOrDefault(it =>
  480. it.Value.Equals(entityInfo.DbTableName, StringComparison.CurrentCultureIgnoreCase) ||
  481. it.Value.Equals(entityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase));
  482. if (easyInfo.Key == null)
  483. {
  484. return;
  485. }
  486. var shortName = this.Builder.GetTranslationColumnName(easyInfo.Key.Trim()) + ".";
  487. sql = GetSql(exp, isSingle);
  488. sql = sql.Replace(itName, shortName);
  489. }
  490. else
  491. {
  492. var easyInfo = JoinQueryInfos.FirstOrDefault(it =>
  493. it.TableName.Equals(entityInfo.DbTableName, StringComparison.CurrentCultureIgnoreCase) ||
  494. it.TableName.Equals(entityInfo.EntityName, StringComparison.CurrentCultureIgnoreCase)||
  495. it.EntityType==ChildType);
  496. if (easyInfo == null)
  497. {
  498. if (ChildType.IsInterface && JoinQueryInfos.Any(it =>it.EntityType!=null&&it.EntityType.GetInterfaces().Any(z => z == ChildType)))
  499. {
  500. easyInfo = JoinQueryInfos.FirstOrDefault(it => it.EntityType.GetInterfaces().Any(z => z == ChildType));
  501. }
  502. else
  503. {
  504. return;
  505. }
  506. }
  507. var shortName = this.Builder.GetTranslationColumnName(easyInfo.ShortName.Trim()) + ".";
  508. sql = GetSql(exp, isSingle);
  509. sql = sql.Replace(itName, shortName);
  510. }
  511. if (item.IsJoinQuery == false||isMain||isSingle|| isEasyJoin)
  512. {
  513. WhereInfos.Add(sql);
  514. }
  515. else
  516. {
  517. var isSameName = !isSingle && this.JoinQueryInfos.Count(it => it.TableName == entityInfo.DbTableName) > 1;
  518. foreach (var joinInfo in this.JoinQueryInfos)
  519. {
  520. var isInterface = ChildType.IsInterface && joinInfo.EntityType != null && joinInfo.EntityType.GetInterfaces().Any(it => it == ChildType);
  521. if (isInterface
  522. && isSameName == false
  523. &&this.JoinQueryInfos.Where(it=> it.EntityType!=null).Count(it => it.EntityType.GetInterfaces().Any(z=>z==ChildType)) > 1)
  524. {
  525. sql = GetSql(exp, false);
  526. var shortName = this.Builder.GetTranslationColumnName(joinInfo.ShortName.Trim()) + ".";
  527. sql = sql.Replace(itName, shortName);
  528. }
  529. if (isInterface||joinInfo.TableName.EqualCase(entityInfo.EntityName)|| joinInfo.TableName.EqualCase(entityInfo.DbTableName)||joinInfo.EntityType==ChildType)
  530. {
  531. var mysql = sql;
  532. if (isSameName)
  533. {
  534. var firstShortName = this.JoinQueryInfos.First(it => it.TableName == entityInfo.DbTableName).ShortName;
  535. mysql = mysql.Replace(Builder.GetTranslationColumnName(firstShortName), Builder.GetTranslationColumnName(joinInfo.ShortName));
  536. }
  537. if (mysql.StartsWith(" WHERE "))
  538. {
  539. mysql = Regex.Replace(mysql, $"^ WHERE ", " AND ");
  540. }
  541. if (isInterface)
  542. {
  543. mysql = ReplaceFilterColumnName(mysql,joinInfo.EntityType,Builder.GetTranslationColumnName(joinInfo.ShortName));
  544. }
  545. joinInfo.JoinWhere=joinInfo.JoinWhere + mysql;
  546. }
  547. }
  548. }
  549. }
  550. private string ReplaceFilterColumnName(string sql, Type filterType,string shortName=null)
  551. {
  552. foreach (var column in this.Context.EntityMaintenance.GetEntityInfoWithAttr(filterType).Columns.Where(it => it.IsIgnore == false))
  553. {
  554. if (shortName == null)
  555. {
  556. sql = sql.Replace(Builder.GetTranslationColumnName(column.PropertyName), Builder.GetTranslationColumnName(column.DbColumnName));
  557. }
  558. else
  559. {
  560. sql = sql.Replace(Builder.GetTranslationColumnName(shortName) + "." + Builder.GetTranslationColumnName(column.PropertyName), Builder.GetTranslationColumnName(shortName) + "." + Builder.GetTranslationColumnName(column.DbColumnName));
  561. sql = sql.Replace(shortName + "."+Builder.GetTranslationColumnName(column.PropertyName), shortName+"." +Builder.GetTranslationColumnName(column.DbColumnName));
  562. }
  563. }
  564. return sql;
  565. }
  566. private string GetSql(Expression exp, bool isSingle)
  567. {
  568. var expValue = GetExpressionValue(exp, isSingle ? ResolveExpressType.WhereSingle : ResolveExpressType.WhereMultiple);
  569. var sql = expValue.GetResultString();
  570. if (WhereInfos.Count == 0)
  571. {
  572. sql = (" WHERE " + sql);
  573. }
  574. else
  575. {
  576. sql = (" AND " + sql);
  577. }
  578. return sql;
  579. }
  580. public virtual string GetExternalOrderBy(string externalOrderBy)
  581. {
  582. return Regex.Replace(externalOrderBy, @"\[\w+\]\.", "");
  583. }
  584. public virtual string ToCountSql(string sql)
  585. {
  586. if (sql != null && sql.Contains("-- No table"))
  587. {
  588. return "-- No table";
  589. }
  590. return string.Format(" SELECT COUNT(1) FROM ({0}) CountTable ", sql);
  591. }
  592. public virtual string ToPageSql(string sql, int? take, int? skip, bool isExternal = false)
  593. {
  594. string temp = isExternal ? ExternalPageTempalte : PageTempalte;
  595. if (skip != null && take == null)
  596. {
  597. return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, long.MaxValue);
  598. }
  599. else if (skip == null && take != null)
  600. {
  601. return string.Format(temp, sql.ToString(), 1, take.ObjToInt());
  602. }
  603. else if (skip != null && take != null)
  604. {
  605. return string.Format(temp, sql.ToString(), skip.ObjToInt() + 1, skip.ObjToInt() + take.ObjToInt());
  606. }
  607. else
  608. {
  609. return sql.ToString();
  610. }
  611. }
  612. public virtual string ToPageSql2(string sql, int? pageIndex, int? pageSize, bool isExternal = false)
  613. {
  614. string temp = isExternal ? ExternalPageTempalte : PageTempalte;
  615. return string.Format(temp, sql.ToString(), (pageIndex - 1) * pageSize + 1, pageIndex * pageSize);
  616. }
  617. public virtual string GetSelectByItems(List<KeyValuePair<string, JoinMapper>> items)
  618. {
  619. var array = items.Select(it => {
  620. JoinMapper dynamicObj = it.Value;
  621. var dbName = Builder.GetTranslationColumnName(dynamicObj.DbName);
  622. var asName = Builder.GetTranslationColumnName(dynamicObj.AsName);
  623. return string.Format("{0}.{1} AS {2}", it.Key, dbName, asName);
  624. });
  625. return string.Join(",", array);
  626. }
  627. public virtual string ToJoinString(JoinQueryInfo joinInfo)
  628. {
  629. var name = joinInfo.TableName;
  630. if (this.AsTables.Any())
  631. {
  632. if (this.Context.MappingTables != null && this.Context.MappingTables.Any(it => it.DbTableName == name))
  633. {
  634. name = this.Context.MappingTables.First(it => it.DbTableName == name).EntityName;
  635. }
  636. if (this.AsTables.Any(it => it.Key == name))
  637. {
  638. name = this.AsTables.First(it => it.Key == name).Value;
  639. }
  640. }
  641. var isSubQuery = name!=null&& name.StartsWith("(") && name.EndsWith(")");
  642. var shortName = joinInfo.ShortName;
  643. if (shortName.HasValue())
  644. {
  645. shortName = this.Builder.GetTranslationColumnName(shortName);
  646. }
  647. var result= string.Format(
  648. this.JoinTemplate,
  649. joinInfo.JoinType.ToString() + UtilConstants.Space,
  650. Builder.GetTranslationTableName(name) + UtilConstants.Space,
  651. shortName + UtilConstants.Space + (TableWithString == SqlWith.Null|| isSubQuery ? " " : TableWithString),
  652. joinInfo.JoinWhere);
  653. if (joinInfo.EntityType!=null&&this.Context.EntityMaintenance.GetEntityInfoWithAttr(joinInfo.EntityType).Discrimator.HasValue())
  654. {
  655. var entityInfo = this.Context.EntityMaintenance.GetEntityInfoWithAttr(joinInfo.EntityType);
  656. result = $" {result} AND {shortName}.{UtilMethods.GetDiscrimator(entityInfo,this.Builder)}";
  657. }
  658. if (joinInfo.JoinType == JoinType.Cross)
  659. {
  660. var onIndex=result.IndexOf(" ON ");
  661. result = result.Substring(0,onIndex);
  662. }
  663. return result;
  664. }
  665. public virtual void Clear()
  666. {
  667. this.Skip = 0;
  668. this.Take = 0;
  669. this.sql = null;
  670. this.WhereIndex = 0;
  671. this.Parameters = null;
  672. this.GroupByValue = null;
  673. this._TableNameString = null;
  674. this.WhereInfos = null;
  675. this.JoinQueryInfos = null;
  676. this.IsDistinct = false;
  677. }
  678. public virtual bool IsComplexModel(string sql)
  679. {
  680. return Regex.IsMatch(sql, @"AS \[\w+\.\w+\]")|| Regex.IsMatch(sql, @"AS \[\w+\.\w+\.\w+\]");
  681. }
  682. public string GetSqlQuerySql(string result)
  683. {
  684. if (this.Hints.HasValue())
  685. {
  686. result = ReplaceHints(result);
  687. }
  688. if (GetTableNameString == " (-- No table ) t ")
  689. {
  690. result = "-- No table ";
  691. return result;
  692. }
  693. if (this.IsSqlQuerySelect == true)
  694. {
  695. return result;
  696. }
  697. if (this.JoinQueryInfos.Count==0&&string.IsNullOrEmpty(OrderByValue)&&this.IsSqlQuery&&this.OldSql.HasValue() && (Skip == null && Take == null) && (this.WhereInfos == null || this.WhereInfos.Count == 0))
  698. {
  699. return this.OldSql;
  700. }
  701. else
  702. {
  703. return result;
  704. }
  705. }
  706. protected virtual string ReplaceHints(string result)
  707. {
  708. result = Regex.Replace(result, "^SELECT ", it =>
  709. {
  710. return $"{it} {Hints} ";
  711. });
  712. return result;
  713. }
  714. protected string SubToListMethod(string result)
  715. {
  716. string oldResult = result;
  717. List<string> names = new List<string>();
  718. var allShortName = new List<string>();
  719. if (IsSingleSubToList())
  720. {
  721. this.TableShortName = (SelectValue as LambdaExpression).Parameters[0].Name;
  722. }
  723. allShortName.Add(this.Builder.SqlTranslationLeft + Builder.GetNoTranslationColumnName(this.TableShortName.ObjToString().ToLower()) + this.Builder.SqlTranslationRight + ".");
  724. if (this.JoinQueryInfos.HasValue())
  725. {
  726. foreach (var item in this.JoinQueryInfos)
  727. {
  728. allShortName.Add(this.Builder.SqlTranslationLeft + Builder.GetNoTranslationColumnName(item.ShortName.ObjToString().ToLower()) + this.Builder.SqlTranslationRight + ".");
  729. }
  730. }
  731. else if (this.EasyJoinInfos != null && this.EasyJoinInfos.Any())
  732. {
  733. Check.ExceptionEasy("No Supprt Subquery.ToList(), Inner Join Or Left Join", "Subquery.ToList请使用Inner方式联表");
  734. }
  735. if (this.TableShortName == null)
  736. {
  737. //Empty
  738. }
  739. else
  740. {
  741. var name = Builder.GetTranslationColumnName(this.TableShortName) + @"\.";
  742. foreach (var paramter in this.SubToListParameters)
  743. {
  744. var regex = $@"\{Builder.SqlTranslationLeft}[\w]{{1,20}}?\{Builder.SqlTranslationRight}\.\{Builder.SqlTranslationLeft}.{{1,50}}?\{Builder.SqlTranslationRight}";
  745. var matches = Regex
  746. .Matches(paramter.Value.ObjToString(), regex, RegexOptions.IgnoreCase).Cast<Match>()
  747. .Where(it => allShortName.Any(z => it.Value.ObjToString().ToLower().Contains(z)))
  748. .Select(it => it.Value).ToList();
  749. names.AddRange(matches);
  750. }
  751. int i = 0;
  752. names = names.Distinct().ToList();
  753. if (names.Any())
  754. {
  755. List<QueryableAppendColumn> colums = new List<QueryableAppendColumn>();
  756. foreach (var item in names)
  757. {
  758. result = (result + $",{item} as app_ext_col_{i}");
  759. colums.Add(new QueryableAppendColumn() { AsName = $"app_ext_col_{i}", Name = item, Index = i });
  760. i++;
  761. }
  762. this.AppendColumns = colums;
  763. }
  764. }
  765. if (HasAppText(oldResult))
  766. {
  767. return oldResult;
  768. }
  769. return result;
  770. }
  771. #endregion
  772. #region Get SQL Partial
  773. public string Offset { get; set; }
  774. public virtual string GetSelectValue
  775. {
  776. get
  777. {
  778. string result = string.Empty;
  779. if (this.SelectValue == null || this.SelectValue is string)
  780. {
  781. result = GetSelectValueByString();
  782. }
  783. else
  784. {
  785. result = GetSelectValueByExpression();
  786. }
  787. if (this.SelectType == ResolveExpressType.SelectMultiple)
  788. {
  789. this.SelectCacheKey = this.SelectCacheKey + string.Join("-", this._JoinQueryInfos.Select(it => it.TableName));
  790. }
  791. if (IsDistinct&&result?.StartsWith("DISTINCT ")!=true)
  792. {
  793. result = " DISTINCT " + result;
  794. }
  795. if (this.SubToListParameters!=null&& this.SubToListParameters.Any())
  796. {
  797. result = SubToListMethod(result);
  798. }
  799. return result;
  800. }
  801. }
  802. public virtual string GetSelectValueByExpression()
  803. {
  804. var expression = this.SelectValue as Expression;
  805. string result = string.Empty;
  806. if (this.IgnoreColumns != null && this.IgnoreColumns.Any())
  807. {
  808. var expArray = GetExpressionValue(expression, this.SelectType).GetResultArray()
  809. .Where(it=>
  810. !this.IgnoreColumns.Any(z=>it.Contains(Builder.GetTranslationColumnName(z)))
  811. ).ToArray();
  812. result =string.Join(",", expArray);
  813. }
  814. else
  815. {
  816. result= GetExpressionValue(expression, this.SelectType).GetResultString();
  817. if (result == null && ExpressionTool.GetMethodName(ExpressionTool.GetLambdaExpressionBody(expression)) == "End")
  818. {
  819. result = GetExpressionValue(expression, ResolveExpressType.FieldSingle).GetResultString();
  820. }
  821. }
  822. if (result == null&& this.AppendNavInfo?.AppendProperties==null)
  823. {
  824. return "*";
  825. }
  826. if (this.AppendNavInfo?.AppendProperties?.Any() ==true)
  827. {
  828. if (result == null)
  829. {
  830. result = "*";
  831. }
  832. result += ",";
  833. var shortName = "";
  834. if (this.TableShortName.HasValue())
  835. {
  836. shortName = $"{Builder.GetTranslationColumnName(this.TableShortName)}.";
  837. }
  838. if (this.GroupByValue.HasValue())
  839. {
  840. result += string.Join(",",this.AppendNavInfo.AppendProperties.Select(it => "max(" + shortName + Builder.GetTranslationColumnName(it.Value) + ") AS SugarNav_" + it.Key));
  841. }
  842. else
  843. {
  844. result += string.Join(",", this.AppendNavInfo.AppendProperties.Select(it => shortName + Builder.GetTranslationColumnName(it.Value) + " AS SugarNav_" + it.Key));
  845. }
  846. }
  847. if (result.Contains("/**/*"))
  848. {
  849. return result.Replace("/**/*", "");
  850. }
  851. if (this.IsSingle() && this.SubToListParameters != null&& expression is LambdaExpression && this.SubToListParameters.Count > 0 && this.TableShortName == null)
  852. {
  853. this.TableShortName =this.Builder.GetTranslationColumnName((expression as LambdaExpression).Parameters[0].Name);
  854. }
  855. if (result.Contains(".*") && this.IsSingle())
  856. {
  857. return "*";
  858. }
  859. else
  860. {
  861. if (expression is LambdaExpression && (expression as LambdaExpression).Body is MethodCallExpression && this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer && this.OrderByValue.HasValue())
  862. {
  863. result = result + " AS columnName";
  864. }
  865. this.SelectCacheKey = result;
  866. return result;
  867. }
  868. }
  869. public virtual string GetSelectValueByString()
  870. {
  871. string result;
  872. if (this.SelectValue.IsNullOrEmpty())
  873. {
  874. string pre = null;
  875. if (this.JoinQueryInfos.HasValue() && this.JoinQueryInfos.Any(it => TableShortName.HasValue()))
  876. {
  877. pre = Builder.GetTranslationColumnName(TableShortName) + ".";
  878. }
  879. var columns = this.Context.EntityMaintenance.GetEntityInfo(this.EntityType).Columns.Where(it => !it.IsIgnore);
  880. if (this.IgnoreColumns.HasValue())
  881. {
  882. columns = columns.Where(c => !this.IgnoreColumns.Any(i => c.PropertyName.Equals(i, StringComparison.CurrentCultureIgnoreCase) || c.DbColumnName.Equals(i, StringComparison.CurrentCultureIgnoreCase))).ToList();
  883. }
  884. result = string.Join(",", columns.Select(it => GetSelectStringByColumnInfo(it, pre)));
  885. }
  886. else
  887. {
  888. result = this.SelectValue.ObjToString();
  889. this.SelectCacheKey = result;
  890. }
  891. if (result.IsNullOrEmpty())
  892. {
  893. result = "*";
  894. }
  895. return result;
  896. }
  897. private string GetSelectStringByColumnInfo(EntityColumnInfo it, string pre)
  898. {
  899. if (it.QuerySql.HasValue())
  900. {
  901. return it.QuerySql+ " AS "+ Builder.GetTranslationColumnName(it.EntityName, it.PropertyName);
  902. }
  903. return pre + Builder.GetTranslationColumnName(it.EntityName, it.PropertyName);
  904. }
  905. public virtual string GetWhereValueString
  906. {
  907. get
  908. {
  909. if (this.WhereInfos == null) return null;
  910. else
  911. {
  912. return string.Join(UtilConstants.Space, this.WhereInfos);
  913. }
  914. }
  915. }
  916. public virtual string GetJoinValueString
  917. {
  918. get
  919. {
  920. if (this.JoinQueryInfos.IsNullOrEmpty()) return null;
  921. else
  922. {
  923. return string.Join(UtilConstants.Space, this.JoinQueryInfos.Select(it => this.ToJoinString(it)));
  924. }
  925. }
  926. }
  927. public virtual string GetTableNameString
  928. {
  929. get
  930. {
  931. var name = EntityName;
  932. if (this.AsTables.Any(it=>it.Key==EntityName))
  933. {
  934. name = this.AsTables.FirstOrDefault(it => it.Key == EntityName).Value;
  935. if (this.IsQueryInQuery && this.SelectValue != null && this.SelectValue is Expression)
  936. {
  937. if (this.SelectValue.ToString().Contains("Subqueryable()")&& name.TrimStart().StartsWith("("))
  938. {
  939. var oldName = name;
  940. name = Regex.Match(name, @"\(.+\)").Value;
  941. if (name.IsNullOrEmpty())
  942. {
  943. name = oldName;
  944. }
  945. }
  946. }
  947. }
  948. var result = Builder.GetTranslationTableName(name);
  949. result += UtilConstants.Space;
  950. if (IsSingle() && result.Contains("MergeTable") && result.Trim().EndsWith(" MergeTable") && TableShortName != null)
  951. {
  952. result = result.Replace(") MergeTable ", ") " + TableShortName+UtilConstants.Space);
  953. TableShortName = null;
  954. }
  955. if (IsSingle() && result.Contains("unionTable") && result.Trim().EndsWith(" unionTable")&& TableShortName!=null)
  956. {
  957. result = result.Replace(" ) unionTable ", ") "+TableShortName + UtilConstants.Space);
  958. TableShortName = null;
  959. }
  960. if (this.TableShortName.HasValue()&&!IsSqlQuery)
  961. {
  962. result += (Builder.GetTranslationColumnName(TableShortName) + UtilConstants.Space);
  963. }
  964. if (this.TableWithString.HasValue() && this.TableWithString != SqlWith.Null)
  965. {
  966. if (!result.TrimStart().StartsWith("("))
  967. {
  968. result += TableWithString + UtilConstants.Space;
  969. }
  970. }
  971. if (!this.IsSingle())
  972. {
  973. result += GetJoinValueString + UtilConstants.Space;
  974. }
  975. if (this.EasyJoinInfos.IsValuable())
  976. {
  977. if (this.TableWithString.HasValue() && this.TableWithString != SqlWith.Null)
  978. {
  979. result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} {2} ", GetTableName(it.Value)," " +Builder.GetTranslationColumnName(it.Key.ObjToString().Trim()), TableWithString)));
  980. }
  981. else
  982. {
  983. result += "," + string.Join(",", this.EasyJoinInfos.Select(it => string.Format("{0} {1} ", GetTableName(it.Value), " " + Builder.GetTranslationColumnName(it.Key.ObjToString().Trim()))));
  984. }
  985. }
  986. return result;
  987. }
  988. }
  989. public virtual string GetOrderByString
  990. {
  991. get
  992. {
  993. if (this.OrderByValue == null) return null;
  994. if (IsCount && this.PartitionByValue.IsNullOrEmpty()) return null;
  995. else
  996. {
  997. return this.OrderByValue;
  998. }
  999. }
  1000. }
  1001. public virtual string GetGroupByString
  1002. {
  1003. get
  1004. {
  1005. if (this.GroupByValue == null) return null;
  1006. if (this.GroupByValue.Last() != ' ')
  1007. {
  1008. return this.GroupByValue + UtilConstants.Space;
  1009. }
  1010. return this.GroupByValue;
  1011. }
  1012. }
  1013. #endregion
  1014. #region NoCopy
  1015. internal List<QueryableFormat> QueryableFormats { get; set; }
  1016. internal bool IsClone { get; set; }
  1017. public bool NoCheckInclude { get; set; }
  1018. public virtual bool IsSelectNoAll { get; set; } = false;
  1019. public List<string> AutoAppendedColumns { get; set; }
  1020. public Dictionary<string, string> MappingKeys { get; set; }
  1021. #endregion
  1022. private string GetTableName(string entityName)
  1023. {
  1024. if (this.AsTables != null && this.AsTables.Any(it=>it.Key==entityName))
  1025. {
  1026. entityName = this.AsTables.First(it => it.Key == entityName).Value;
  1027. }
  1028. var result = this.Context.EntityMaintenance.GetTableName(entityName);
  1029. return this.Builder.GetTranslationTableName(result);
  1030. }
  1031. public void CheckExpression(Expression expression, string methodName)
  1032. {
  1033. if (IsSingle() == false && this.JoinExpression != null)
  1034. {
  1035. var jsoinParameters = (this.JoinExpression as LambdaExpression).Parameters;
  1036. var currentParametres = (expression as LambdaExpression).Parameters;
  1037. if ((expression as LambdaExpression).Body.ToString() == "True")
  1038. {
  1039. return;
  1040. }
  1041. if (currentParametres != null && currentParametres.Count > 0)
  1042. {
  1043. foreach (var item in currentParametres)
  1044. {
  1045. var index = currentParametres.IndexOf(item);
  1046. var name = item.Name;
  1047. var joinName = jsoinParameters[index].Name;
  1048. Check.Exception(name.ToLower() != joinName.ToLower(), ErrorMessage.ExpressionCheck, joinName, methodName, name);
  1049. }
  1050. }
  1051. }
  1052. }
  1053. public void CheckExpressionNew(Expression expression, string methodName)
  1054. {
  1055. if (IsSingle() == false && this.JoinExpression != null)
  1056. {
  1057. var jsoinParameters = (this.JoinExpression as LambdaExpression).Parameters;
  1058. var currentParametres = (expression as LambdaExpression).Parameters;
  1059. if ((expression as LambdaExpression).Body.ToString() == "True")
  1060. {
  1061. return;
  1062. }
  1063. if (currentParametres != null && currentParametres.Count > 0)
  1064. {
  1065. if (jsoinParameters.Count + 1 != currentParametres.Count)
  1066. {
  1067. var str1 = "(" + string.Join(",", currentParametres.Select(it => it.Name)) + ")=>";
  1068. var str2 = "("+string.Join(",", jsoinParameters.Select(it => it.Name))+","+ currentParametres.Last().Type.Name + " )=>";
  1069. throw new Exception(ErrorMessage.GetThrowMessage($"Join {currentParametres.Last().Type.Name} error , Please change {str1} to {str2}.", $"Join {currentParametres.Last().Type.Name} 错误, 请把 {str1} 改成 {str2} "));
  1070. }
  1071. foreach (var item in currentParametres.Take(jsoinParameters.Count))
  1072. {
  1073. var index = currentParametres.IndexOf(item);
  1074. var name = item.Name;
  1075. var joinName = jsoinParameters[index].Name;
  1076. Check.Exception(name.ToLower() != joinName.ToLower(), ErrorMessage.ExpressionCheck, joinName, methodName, name);
  1077. }
  1078. }
  1079. }
  1080. }
  1081. private bool IsSingleSubToList()
  1082. {
  1083. return this.SubToListParameters != null
  1084. && this.TableShortName == null
  1085. && this.SelectValue is Expression
  1086. && this.IsSingle();
  1087. }
  1088. private static bool HasAppText(string result)
  1089. {
  1090. return result.HasValue() && result.Contains("app_ext_col_0");
  1091. }
  1092. }
  1093. }