123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace SqlSugar
- {
- public class UpdateBuilder : IDMLBuilder
- {
- public UpdateBuilder()
- {
- this.sql = new StringBuilder();
- this.DbColumnInfoList = new List<DbColumnInfo>();
- this.SetValues = new List<KeyValuePair<string, string>>();
- this.WhereValues = new List<string>();
- this.Parameters = new List<SugarParameter>();
- }
- public SqlSugarProvider Context { get; set; }
- public ILambdaExpressions LambdaExpressions { get; set; }
- public ISqlBuilder Builder { get; set; }
- public StringBuilder sql { get; set; }
- public List<SugarParameter> Parameters { get; set; }
- public string TableName { get; set; }
- public string TableWithString { get; set; }
- public List<DbColumnInfo> DbColumnInfoList { get; set; }
- public List<string> WhereValues { get; set; }
- public string AppendWhere { get; set; }
- public List<KeyValuePair<string, string>> SetValues { get; set; }
- public bool IsNoUpdateNull { get; set; }
- public bool IsNoUpdateDefaultValue { get; set; }
- public List<string> PrimaryKeys { get; set; }
- public List<string> OldPrimaryKeys { get; set; }
- public bool IsOffIdentity { get; set; }
- public bool IsWhereColumns { get; set; }
- public bool? IsListUpdate { get; set; }
- public List<string> UpdateColumns { get; set; }
- public List<JoinQueryInfo> JoinInfos { get; set; }
- public string ShortName { get; set; }
- public Dictionary<string, ReSetValueBySqlExpListModel> ReSetValueBySqlExpList { get; set; }
- public virtual string ReSetValueBySqlExpListType { get; set; }
- public EntityInfo EntityInfo { get; set; }
- public virtual string SqlTemplate
- {
- get
- {
- return @"UPDATE {0} SET
- {1} {2}";
- }
- }
- public virtual string SqlTemplateBatch
- {
- get
- {
- return @"UPDATE S SET {0} FROM {1} S {2} INNER JOIN ";
- }
- }
- public virtual string SqlTemplateJoin
- {
- get
- {
- return @" (
- {0}
- ) T ON {1}
- ; ";
- }
- }
- public virtual string SqlTemplateBatchSet
- {
- get
- {
- return "{0} AS {1}";
- }
- }
- public virtual string SqlTemplateBatchSelect
- {
- get
- {
- return "{0} AS {1}";
- }
- }
- public virtual string SqlTemplateBatchUnion
- {
- get
- {
- return "\t\t\r\nUNION ALL ";
- }
- }
- public virtual void Clear()
- {
- }
- public virtual string GetTableNameString
- {
- get
- {
- var result = Builder.GetTranslationTableName(TableName);
- result += UtilConstants.Space;
- if (this.TableWithString.HasValue())
- {
- result += TableWithString + UtilConstants.Space;
- }
- return result;
- }
- }
- public virtual string GetTableNameStringNoWith
- {
- get
- {
- var result = Builder.GetTranslationTableName(TableName);
- return result;
- }
- }
- public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType, bool isMapping = true)
- {
- ILambdaExpressions resolveExpress = this.LambdaExpressions;
- this.LambdaExpressions.Clear();
- if (this.Context.CurrentConnectionConfig.MoreSettings != null)
- {
- resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower;
- resolveExpress.TableEnumIsString = this.Context.CurrentConnectionConfig.MoreSettings.TableEnumIsString;
- }
- else
- {
- resolveExpress.PgSqlIsAutoToLower = true;
- }
- if (isMapping)
- {
- resolveExpress.MappingColumns = Context.MappingColumns;
- resolveExpress.MappingTables = Context.MappingTables;
- resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
- resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
- }
- resolveExpress.InitMappingInfo = Context.InitMappingInfo;
- resolveExpress.RefreshMapping = () =>
- {
- resolveExpress.MappingColumns = Context.MappingColumns;
- resolveExpress.MappingTables = Context.MappingTables;
- resolveExpress.IgnoreComumnList = Context.IgnoreColumns;
- resolveExpress.SqlFuncServices = Context.CurrentConnectionConfig.ConfigureExternalServices == null ? null : Context.CurrentConnectionConfig.ConfigureExternalServices.SqlFuncServices;
- };
- resolveExpress.SugarContext = new ExpressionOutParameter() { Context = this.Context };
- resolveExpress.Resolve(expression, resolveType);
- this.Parameters.AddRange(resolveExpress.Parameters);
- var result = resolveExpress.Result;
- return result;
- }
- public virtual string ToSqlString()
- {
- if (IsNoUpdateNull)
- {
- DbColumnInfoList = DbColumnInfoList.Where(it => it.Value != null||(it.UpdateServerTime == true ||!string.IsNullOrEmpty(it.UpdateSql))).ToList();
- }
- if (IsNoUpdateDefaultValue)
- {
- DbColumnInfoList = DbColumnInfoList.Where(it => {
- if (it.Value.ObjToString() == "0" && it.PropertyType.IsEnum)
- {
- return it.Value.ObjToLong() != UtilMethods.DefaultForType(it.PropertyType).ObjToLong();
- }
- else if (it.UpdateServerTime == true || !string.IsNullOrEmpty(it.UpdateSql))
- {
- return true;
- }
- else
- {
- return it.Value.ObjToString() != UtilMethods.DefaultForType(it.PropertyType).ObjToString();
- }
- }).ToList();
- }
- var groupList = DbColumnInfoList.GroupBy(it => it.TableId).ToList();
- var isSingle = groupList.Count() == 1;
- if (isSingle&&this.IsListUpdate==null)
- {
- ActionMinDate();
- return ToSingleSqlString(groupList);
- }
- else
- {
- return TomultipleSqlString(groupList);
- }
- }
- protected virtual string TomultipleSqlString(List<IGrouping<int, DbColumnInfo>> groupList)
- {
- Check.Exception(PrimaryKeys == null || PrimaryKeys.Count == 0, " Update List<T> need Primary key");
- int pageSize = 200;
- int pageIndex = 1;
- int totalRecord = groupList.Count;
- int pageCount = (totalRecord + pageSize - 1) / pageSize;
- StringBuilder batchUpdateSql = new StringBuilder();
- while (pageCount >= pageIndex)
- {
- StringBuilder updateTable = new StringBuilder();
- string setValues = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it =>
- {
- if (SetValues.IsValuable())
- {
- var setValue = SetValues.Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName));
- if (setValue != null && setValue.Any())
- {
- return setValue.First().Value;
- }
- }
- var result = string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(it.DbColumnName));
- return result;
- }));
- batchUpdateSql.AppendFormat(SqlTemplateBatch.ToString(), setValues, GetTableNameStringNoWith, TableWithString);
- int i = 0;
- foreach (var columns in groupList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList())
- {
- var isFirst = i == 0;
- if (!isFirst)
- {
- updateTable.Append(SqlTemplateBatchUnion);
- }
- updateTable.Append("\r\n SELECT " + string.Join(",", columns.Select(it => string.Format(SqlTemplateBatchSelect, FormatValue(it.Value), Builder.GetTranslationColumnName(it.DbColumnName)))));
- ++i;
- }
- pageIndex++;
- updateTable.Append("\r\n");
- string whereString = null;
- if (this.WhereValues.HasValue())
- {
- foreach (var item in WhereValues)
- {
- var isFirst = whereString == null;
- whereString += (isFirst ? null : " AND ");
- whereString += Regex.Replace(item,"\\"+this.Builder.SqlTranslationLeft,"S."+ this.Builder.SqlTranslationLeft);
- }
- }
- if (PrimaryKeys.HasValue())
- {
- foreach (var item in PrimaryKeys)
- {
- var isFirst = whereString == null;
- whereString += (isFirst ? null : " AND ");
- whereString += string.Format("S.{0}=T.{0}", Builder.GetTranslationColumnName(item));
- }
- }
- batchUpdateSql.AppendFormat(SqlTemplateJoin, updateTable, whereString);
- }
- return batchUpdateSql.ToString();
- }
- protected virtual string ToSingleSqlString(List<IGrouping<int, DbColumnInfo>> groupList)
- {
- string columnsString = string.Join(",", groupList.First().Where(it => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Select(it =>
- {
- if (SetValues.IsValuable())
- {
- var setValue = SetValues.Where(sv => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Where(sv => sv.Key == Builder.GetTranslationColumnName(it.DbColumnName) || sv.Key == Builder.GetTranslationColumnName(it.PropertyName));
- if (setValue != null && setValue.Any())
- {
- return setValue.First().Value;
- }
- else if (JoinInfos!=null&&JoinInfos.Any())
- {
- setValue = SetValues.Where(sv => it.IsPrimarykey == false && (it.IsIdentity == false || (IsOffIdentity && it.IsIdentity))).Where(sv => sv.Key == Builder.GetNoTranslationColumnName(it.DbColumnName) || sv.Key == Builder.GetNoTranslationColumnName(it.PropertyName));
- return Builder.GetTranslationColumnName(this.ShortName)+"."+ setValue.First().Key+"="+ setValue.First().Value ;
- }
- }
- var result = Builder.GetTranslationColumnName(it.DbColumnName) + "=" + GetDbColumn(it,this.Context.Ado.SqlParameterKeyWord + it.DbColumnName);
- return result;
- }));
- string whereString = null;
- if (this.WhereValues.HasValue())
- {
- foreach (var item in WhereValues)
- {
- var isFirst = whereString == null;
- whereString += (isFirst ? " WHERE " : " AND ");
- whereString += item;
- }
- }
- else if (PrimaryKeys.HasValue())
- {
- if (IsWhereColumns == false)
- {
- int i = 100000;
- foreach (var item in PrimaryKeys)
- {
- i++;
- var isFirst = whereString == null;
- whereString += (isFirst ? " WHERE " : " AND ");
- var pkIsSugarDataConverter = GetPkIsSugarDataConverter();
- if (pkIsSugarDataConverter && GetColumnInfo(item)!=null)
- {
- var columnInfo = GetColumnInfo(item);
- var value=this.DbColumnInfoList.FirstOrDefault(it => it.DbColumnName.EqualCase(item) || it.PropertyName.EqualCase(item))?.Value;
- var p = UtilMethods.GetParameterConverter(i, this.Context, value, this.EntityInfo, this.EntityInfo?.Columns.First(it => it.DbColumnName.Equals(item) || it.PropertyName.Equals(item)));
- whereString += Builder.GetTranslationColumnName(item) + "=" + p.ParameterName;
- this.Parameters.Add(p);
- }
- else
- {
- whereString += Builder.GetTranslationColumnName(item) + "=" + this.Context.Ado.SqlParameterKeyWord + item;
- }
- }
- }
- }
- if (PrimaryKeys.HasValue()&&IsWhereColumns)
- {
- foreach (var item in PrimaryKeys)
- {
- var isFirst = whereString == null;
- whereString += (isFirst ? " WHERE " : " AND ");
- whereString += Builder.GetTranslationColumnName(item) + "=" + this.Context.Ado.SqlParameterKeyWord + item;
- }
- }
- if (this.JoinInfos != null && this.JoinInfos.Any())
- {
- return GetJoinUpdate(columnsString, ref whereString);
- }
- return string.Format(SqlTemplate, GetTableNameString, columnsString, whereString);
- }
- private EntityColumnInfo GetColumnInfo(string item)
- {
- var columnInfo= this.EntityInfo?.Columns?.FirstOrDefault(it => it.DbColumnName.Equals(item) || it.PropertyName.Equals(item));
- return columnInfo;
- }
- private bool GetPkIsSugarDataConverter()
- {
- return this.EntityInfo?.Columns.Any(it => it.IsPrimarykey && it.SqlParameterDbType is Type&&typeof(ISugarDataConverter).IsAssignableFrom((it.SqlParameterDbType as Type))) == true;
- }
- protected virtual string GetJoinUpdate(string columnsString, ref string whereString)
- {
- var tableName = Builder.GetTranslationColumnName(this.TableName);
- this.TableName = Builder.GetTranslationColumnName(this.ShortName);
- var joinString = $" FROM {tableName} {Builder.GetTranslationColumnName(this.ShortName)} ";
- foreach (var item in this.JoinInfos)
- {
- joinString += $"\r\n JOIN {Builder.GetTranslationColumnName(item.TableName)} {Builder.GetTranslationColumnName(item.ShortName)} ON {item.JoinWhere} ";
- }
- whereString = joinString + "\r\n" + whereString;
- return string.Format(SqlTemplate, GetTableNameString, columnsString, whereString);
- }
- public virtual void ActionMinDate()
- {
- if (this.Parameters != null)
- {
- foreach (var item in this.Parameters)
- {
- if (item.DbType == System.Data.DbType.Date || item.DbType == System.Data.DbType.DateTime)
- {
- if (item.Value != null && item.Value != DBNull.Value)
- {
- if (item.Value is DateTime)
- {
- if (Convert.ToDateTime(item.Value) == DateTime.MinValue)
- {
- item.Value = UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig);
- }
- }
- }
- }
- }
- }
- }
- public virtual object FormatValue(object value)
- {
- if (value == null)
- {
- return "NULL";
- }
- else
- {
- var type = UtilMethods.GetUnderType(value.GetType());
- if (type == UtilConstants.DateType)
- {
- var date = value.ObjToDate();
- if (date < UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig))
- {
- date = UtilMethods.GetMinDate(this.Context.CurrentConnectionConfig);
- }
- return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
- }
- else if (type == UtilConstants.ByteArrayType)
- {
- string bytesString = "0x" + BitConverter.ToString((byte[])value).Replace("-", "");
- return bytesString;
- }
- else if (type.IsEnum())
- {
- if (this.Context.CurrentConnectionConfig.MoreSettings?.TableEnumIsString == true)
- {
- return value.ToSqlValue();
- }
- else
- {
- return Convert.ToInt64(value);
- }
- }
- else if (type == UtilConstants.BoolType)
- {
- return value.ObjToBool() ? "1" : "0";
- }
- else if (type == UtilConstants.DateTimeOffsetType)
- {
- return FormatDateTimeOffset(value);
- }
- else if (type == UtilConstants.StringType || type == UtilConstants.ObjType)
- {
- return "N'" + value.ToString().ToSqlFilter() + "'";
- }
- else if (type==UtilConstants.IntType||type==UtilConstants.LongType)
- {
- return value;
- }
- else if (UtilMethods.IsNumber(type.Name))
- {
- if (value.ObjToString().Contains(","))
- {
- return $"'{value}'";
- }
- else
- {
- return value;
- }
- }
- else
- {
- return "N'" + value.ToString() + "'";
- }
- }
- }
- public virtual string FormatDateTimeOffset(object value)
- {
- var date = UtilMethods.ConvertFromDateTimeOffset((DateTimeOffset)value);
- return "'" + date.ToString("yyyy-MM-dd HH:mm:ss.fff") + "'";
- }
- private int GetDbColumnIndex = 0;
- public virtual string GetDbColumn(DbColumnInfo columnInfo, object name)
- {
- if (columnInfo.UpdateServerTime)
- {
- return LambdaExpressions.DbMehtods.GetDate();
- }
- else if (UtilMethods.IsErrorDecimalString()==true)
- {
- var pname = Builder.SqlParameterKeyWord + "Decimal" + GetDbColumnIndex;
- var p = new SugarParameter(pname, columnInfo.Value);
- this.Parameters.Add(p);
- GetDbColumnIndex++;
- return pname;
- }
- else if (IsListSetExp(columnInfo) || IsSingleSetExp(columnInfo))
- {
- if (this.ReSetValueBySqlExpList[columnInfo.PropertyName].Type == ReSetValueBySqlExpListModelType.List)
- {
- return Builder.GetTranslationColumnName(columnInfo.DbColumnName) + this.ReSetValueBySqlExpList[columnInfo.PropertyName].Sql + name;
- }
- else
- {
- return this.ReSetValueBySqlExpList[columnInfo.PropertyName].Sql;
- }
- }
- else if (columnInfo.UpdateSql.HasValue())
- {
- return columnInfo.UpdateSql;
- }
- else if (columnInfo.SqlParameterDbType is Type && (Type)columnInfo.SqlParameterDbType == UtilConstants.SqlConvertType)
- {
- var type = columnInfo.SqlParameterDbType as Type;
- var ParameterConverter = type.GetMethod("ParameterConverter").MakeGenericMethod(typeof(string));
- var obj = Activator.CreateInstance(type);
- var p = ParameterConverter.Invoke(obj, new object[] { columnInfo.Value, GetDbColumnIndex }) as SugarParameter;
- return p.ParameterName;
- }
- else if (columnInfo.SqlParameterDbType is Type)
- {
- var type = columnInfo.SqlParameterDbType as Type;
- var ParameterConverter = type.GetMethod("ParameterConverter").MakeGenericMethod(columnInfo.PropertyType);
- var obj = Activator.CreateInstance(type);
- var p = ParameterConverter.Invoke(obj, new object[] { columnInfo.Value, GetDbColumnIndex }) as SugarParameter;
- GetDbColumnIndex++;
- //this.Parameters.RemoveAll(it => it.ParameterName == it.ParameterName);
- this.Parameters.Add(p);
- return p.ParameterName;
- }
- else if (columnInfo.PropertyType != null && columnInfo.PropertyType.Name == "TimeOnly" && name != null && !name.ObjToString().StartsWith(Builder.SqlParameterKeyWord))
- {
- var timeSpan = UtilMethods.TimeOnlyToTimeSpan(columnInfo.Value);
- var pname = Builder.SqlParameterKeyWord + columnInfo.DbColumnName + "_ts" + GetDbColumnIndex;
- if (timeSpan == null)
- {
- this.Parameters.Add(new SugarParameter(pname, null) { DbType = System.Data.DbType.Date });
- }
- else
- {
- this.Parameters.Add(new SugarParameter(pname, timeSpan));
- }
- GetDbColumnIndex++;
- return pname;
- }
- else if (columnInfo.PropertyType != null && columnInfo.PropertyType.Name == "DateOnly")
- {
- var timeSpan = UtilMethods.DateOnlyToDateTime(columnInfo.Value);
- var pname = Builder.SqlParameterKeyWord + columnInfo.DbColumnName + "_ts" + GetDbColumnIndex;
- if (timeSpan == null)
- {
- this.Parameters.Add(new SugarParameter(pname, null) { DbType = System.Data.DbType.Date });
- }
- else
- {
- this.Parameters.Add(new SugarParameter(pname, Convert.ToDateTime(timeSpan)));
- }
- GetDbColumnIndex++;
- return pname;
- }
- else if (UtilMethods.IsErrorParameterName(this.Context.CurrentConnectionConfig, columnInfo))
- {
- var pname = Builder.SqlParameterKeyWord + "CrorrPara" + GetDbColumnIndex;
- var p = new SugarParameter(pname, columnInfo.Value);
- this.Parameters.Add(p);
- GetDbColumnIndex++;
- return pname;
- }
- else
- {
- return name + "";
- }
- }
- private bool IsSingleSetExp(DbColumnInfo columnInfo)
- {
- return this.ReSetValueBySqlExpList != null &&
- this.ReSetValueBySqlExpList.ContainsKey(columnInfo.PropertyName) &&
- this.IsListUpdate == null&&
- DbColumnInfoList.GroupBy(it => it.TableId).Count()==1;
- }
- private bool IsListSetExp(DbColumnInfo columnInfo)
- {
- return this.ReSetValueBySqlExpListType != null && this.ReSetValueBySqlExpList != null && this.ReSetValueBySqlExpList.ContainsKey(columnInfo.PropertyName);
- }
- //public virtual string GetDbColumn(DbColumnInfo columnInfo, string name)
- //{
- // if (columnInfo.UpdateServerTime)
- // {
- // return LambdaExpressions.DbMehtods.GetDate();
- // }
- // else if (columnInfo.UpdateSql.HasValue())
- // {
- // return columnInfo.UpdateSql;
- // }
- // else
- // {
- // return name + "";
- // }
- //}
- }
- }
|