InsertBuilder.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Linq;
  5. using System.Linq.Expressions;
  6. namespace SqlSugar
  7. {
  8. public partial class InsertBuilder : IDMLBuilder
  9. {
  10. #region Init
  11. public InsertBuilder()
  12. {
  13. this.sql = new StringBuilder();
  14. this.Parameters = new List<SugarParameter>();
  15. this.DbColumnInfoList = new List<DbColumnInfo>();
  16. }
  17. #endregion
  18. #region Common Properties
  19. public SqlSugarProvider Context { get; set; }
  20. public ILambdaExpressions LambdaExpressions { get; set; }
  21. public ISqlBuilder Builder { get; set; }
  22. public StringBuilder sql { get; set; }
  23. public List<SugarParameter> Parameters { get; set; }
  24. public string TableWithString { get; set; }
  25. public List<DbColumnInfo> DbColumnInfoList { get; set; }
  26. public bool IsNoInsertNull { get; set; }
  27. public bool IsReturnIdentity { get; set; }
  28. public EntityInfo EntityInfo { get; set; }
  29. public Dictionary<string, int> OracleSeqInfoList { get; set; }
  30. public bool IsBlukCopy { get; set; }
  31. public virtual bool IsOleDb { get; set; }
  32. public virtual Func<string, string, string> ConvertInsertReturnIdFunc { get; set; }
  33. public virtual bool IsNoPage { get; set; }
  34. public virtual bool IsReturnPkList { get; set; }
  35. public string AsName { get; set; }
  36. public bool IsOffIdentity { get; set; }
  37. #endregion
  38. #region SqlTemplate
  39. public virtual string SqlTemplate
  40. {
  41. get
  42. {
  43. if (IsReturnIdentity)
  44. {
  45. return @"INSERT INTO {0}
  46. ({1})
  47. VALUES
  48. ({2}) ;SELECT SCOPE_IDENTITY();";
  49. }
  50. else
  51. {
  52. return @"INSERT INTO {0}
  53. ({1})
  54. VALUES
  55. ({2}) ;";
  56. }
  57. }
  58. }
  59. public virtual string SqlTemplateBatch
  60. {
  61. get
  62. {
  63. return "INSERT {0} ({1})";
  64. }
  65. }
  66. public virtual string SqlTemplateBatchSelect
  67. {
  68. get
  69. {
  70. return "{0} AS {1}";
  71. }
  72. }
  73. public virtual string SqlTemplateBatchUnion
  74. {
  75. get
  76. {
  77. return "\t\r\nUNION ALL ";
  78. }
  79. }
  80. #endregion
  81. #region Methods
  82. public virtual void ActionMinDate()
  83. {
  84. if (this.Parameters != null)
  85. {
  86. foreach (var item in this.Parameters)
  87. {
  88. if (item.DbType == System.Data.DbType.Date || item.DbType == System.Data.DbType.DateTime)
  89. {
  90. if (item.Value != null && item.Value != DBNull.Value)
  91. {
  92. if (item.Value is DateTime)
  93. {
  94. if (Convert.ToDateTime(item.Value) == DateTime.MinValue)
  95. {
  96. item.Value = UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig);
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }
  103. }
  104. public virtual void Clear()
  105. {
  106. }
  107. public virtual string GetTableNameString
  108. {
  109. get
  110. {
  111. if (AsName.HasValue())
  112. {
  113. return Builder.GetTranslationTableName(AsName);
  114. }
  115. var result = Builder.GetTranslationTableName(EntityInfo.EntityName);
  116. result += UtilConstants.Space;
  117. if (this.TableWithString.HasValue())
  118. {
  119. result += TableWithString + UtilConstants.Space;
  120. }
  121. return result;
  122. }
  123. }
  124. public bool MySqlIgnore { get; internal set; }
  125. public bool IsWithAttr { get; internal set; }
  126. public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType)
  127. {
  128. ILambdaExpressions resolveExpress = this.LambdaExpressions;
  129. this.LambdaExpressions.Clear();
  130. if (this.Context.CurrentConnectionConfig.MoreSettings != null)
  131. {
  132. resolveExpress.TableEnumIsString = this.Context.CurrentConnectionConfig.MoreSettings.TableEnumIsString;
  133. resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
  134. }
  135. else
  136. {
  137. resolveExpress.PgSqlIsAutoToLower = true;
  138. }
  139. resolveExpress.MappingColumns = Context.MappingColumns;
  140. resolveExpress.MappingTables = Context.MappingTables;
  141. resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
  142. resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
  143. resolveExpress.Resolve(expression, resolveType);
  144. this.Parameters.AddRange(resolveExpress.Parameters);
  145. var result = resolveExpress.Result;
  146. return result;
  147. }
  148. public virtual string ToSqlString()
  149. {
  150. if (IsNoInsertNull)
  151. {
  152. DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null).ToList();
  153. }
  154. var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList();
  155. var isSingle = groupList.Count() == 1;
  156. string columnsString = string.Join(",", groupList.First().Select(it => Builder.GetTranslationColumnName(it.DbColumnName)));
  157. if (isSingle)
  158. {
  159. string columnParametersString = string.Join(",", this.DbColumnInfoList.Select(it =>this.GetDbColumn(it, Builder.SqlParameterKeyWord + it.DbColumnName)));
  160. return string.Format(SqlTemplate, GetTableNameString, columnsString, columnParametersString);
  161. }
  162. else
  163. {
  164. StringBuilder batchInsetrSql = new StringBuilder();
  165. int pageSize = 200;
  166. if (this.EntityInfo.Columns.Count > 30)
  167. {
  168. pageSize = 50;
  169. }
  170. else if (this.EntityInfo.Columns.Count > 20)
  171. {
  172. pageSize = 100;
  173. }
  174. int pageIndex = 1;
  175. int totalRecord = groupList.Count;
  176. int pageCount = (totalRecord + pageSize - 1) / pageSize;
  177. while (pageCount >= pageIndex)
  178. {
  179. batchInsetrSql.AppendFormat(SqlTemplateBatch, GetTableNameString, columnsString);
  180. int i = 0;
  181. foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList())
  182. {
  183. var isFirst = i == 0;
  184. if (!isFirst)
  185. {
  186. batchInsetrSql.Append(SqlTemplateBatchUnion);
  187. }
  188. batchInsetrSql.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect,this.GetDbColumn(it, FormatValue(it.Value)),Builder.GetTranslationColumnName(it.DbColumnName)))));
  189. ++i;
  190. }
  191. pageIndex++;
  192. batchInsetrSql.Append("\r\n;\r\n");
  193. }
  194. var result= batchInsetrSql.ToString();
  195. if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer)
  196. {
  197. result += "select @@identity;";
  198. }
  199. return result;
  200. }
  201. }
  202. public virtual object FormatValue(object value)
  203. {
  204. var N = "N";
  205. if (this.Context.CurrentConnectionConfig.DbType == DbType.Sqlite)
  206. {
  207. N = "";
  208. }
  209. if (value == null)
  210. {
  211. return "NULL";
  212. }
  213. else
  214. {
  215. var type =UtilMethods.GetUnderType(value.GetType());
  216. if (type == UtilConstants.DateType)
  217. {
  218. var date = value.ObjToDate();
  219. if (date < UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig))
  220. {
  221. date = UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig);
  222. }
  223. return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
  224. }
  225. else if (type == UtilConstants.ByteArrayType)
  226. {
  227. string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", "");
  228. return bytesString;
  229. }
  230. else if (type.IsEnum())
  231. {
  232. if (this.Context.CurrentConnectionConfig.MoreSettings?.TableEnumIsString == true)
  233. {
  234. return value.ToSqlValue();
  235. }
  236. else
  237. {
  238. return Convert.ToInt64(value);
  239. }
  240. }
  241. else if (type == UtilConstants.BoolType)
  242. {
  243. return value.ObjToBool() ? "1" : "0";
  244. }
  245. else if (type == UtilConstants.StringType || type == UtilConstants.ObjType)
  246. {
  247. return N+"'" + value.ToString().ToSqlFilter() + "'";
  248. }
  249. else if (type == UtilConstants.DateTimeOffsetType)
  250. {
  251. return FormatDateTimeOffset(value);
  252. }
  253. else if (type == UtilConstants.FloatType)
  254. {
  255. return N+"'" +Convert.ToDouble(value).ToString() + "'";
  256. }
  257. else
  258. {
  259. return N+"'" + value.ToString() + "'";
  260. }
  261. }
  262. }
  263. public virtual string FormatDateTimeOffset(object value)
  264. {
  265. var date = UtilMethods.ConvertFromDateTimeOffset((DateTimeOffset)value);
  266. return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
  267. }
  268. private int GetDbColumnIndex = 0;
  269. public virtual string GetDbColumn(DbColumnInfo columnInfo ,object name)
  270. {
  271. if (columnInfo.InsertServerTime)
  272. {
  273. return LambdaExpressions.DbMehtods.GetDate();
  274. }
  275. else if (UtilMethods.IsErrorDecimalString() == true)
  276. {
  277. var pname = Builder.SqlParameterKeyWord + "Decimal" + GetDbColumnIndex;
  278. var p = new SugarParameter(pname, columnInfo.Value);
  279. this.Parameters.Add(p);
  280. GetDbColumnIndex++;
  281. return pname;
  282. }
  283. else if (columnInfo.InsertSql.HasValue())
  284. {
  285. return columnInfo.InsertSql;
  286. }
  287. else if (columnInfo.SqlParameterDbType is Type && (Type)columnInfo.SqlParameterDbType == UtilConstants.SqlConvertType)
  288. {
  289. var type = columnInfo.SqlParameterDbType as Type;
  290. var ParameterConverter = type.GetMethod("ParameterConverter").MakeGenericMethod(typeof(string));
  291. var obj = Activator.CreateInstance(type);
  292. var p = ParameterConverter.Invoke(obj, new object[] { columnInfo.Value, GetDbColumnIndex }) as SugarParameter;
  293. return p.ParameterName;
  294. }
  295. else if (columnInfo.SqlParameterDbType is Type)
  296. {
  297. var type=columnInfo.SqlParameterDbType as Type;
  298. var ParameterConverter=type.GetMethod("ParameterConverter").MakeGenericMethod(columnInfo.PropertyType);
  299. var obj=Activator.CreateInstance(type);
  300. var p = ParameterConverter.Invoke(obj,new object[] {columnInfo.Value, GetDbColumnIndex }) as SugarParameter;
  301. GetDbColumnIndex++;
  302. //this.Parameters.RemoveAll(it => it.ParameterName == it.ParameterName);
  303. UtilMethods.ConvertParameter(p,this.Builder);
  304. this.Parameters.Add(p);
  305. return p.ParameterName;
  306. }
  307. else if (columnInfo.DataType?.Equals("nvarchar2")==true)
  308. {
  309. var pname = Builder.SqlParameterKeyWord + columnInfo.DbColumnName + "_ts" + GetDbColumnIndex;
  310. var p = new SugarParameter(pname, columnInfo.Value);
  311. p.IsNvarchar2 = true;
  312. this.Parameters.Add(p);
  313. GetDbColumnIndex++;
  314. return pname;
  315. }
  316. else if (columnInfo.PropertyType!=null&&columnInfo.PropertyType.Name == "TimeOnly" )
  317. {
  318. var timeSpan = UtilMethods.TimeOnlyToTimeSpan(columnInfo.Value);
  319. var pname = Builder.SqlParameterKeyWord + columnInfo.DbColumnName + "_ts" + GetDbColumnIndex;
  320. this.Parameters.Add(new SugarParameter(pname, timeSpan));
  321. GetDbColumnIndex++;
  322. return pname;
  323. }
  324. else if (columnInfo.PropertyType != null && columnInfo.PropertyType.Name == "DateOnly")
  325. {
  326. var timeSpan = UtilMethods.DateOnlyToDateTime(columnInfo.Value);
  327. var pname = Builder.SqlParameterKeyWord + columnInfo.DbColumnName + "_ts" + GetDbColumnIndex;
  328. if (timeSpan == null)
  329. {
  330. this.Parameters.Add(new SugarParameter(pname, null) { DbType=System.Data.DbType.Date });
  331. }
  332. else
  333. {
  334. this.Parameters.Add(new SugarParameter(pname, Convert.ToDateTime(timeSpan)));
  335. }
  336. GetDbColumnIndex++;
  337. return pname;
  338. }
  339. else if (UtilMethods.IsErrorParameterName(this.Context.CurrentConnectionConfig, columnInfo))
  340. {
  341. var pname = Builder.SqlParameterKeyWord + "CrorrPara" + GetDbColumnIndex;
  342. var p = new SugarParameter(pname, columnInfo.Value);
  343. this.Parameters.Add(p);
  344. GetDbColumnIndex++;
  345. return pname;
  346. }
  347. else
  348. {
  349. return name + "";
  350. }
  351. }
  352. #endregion
  353. }
  354. }