using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public class DeleteableProvider : IDeleteable where T : class, new() { public SqlSugarClient Context { get; set; } public IAdo Db { get { return Context.Ado; } } public ISqlBuilder SqlBuilder { get; set; } public DeleteBuilder DeleteBuilder { get; set; } public MappingTableList OldMappingTableList { get; set; } public bool IsAs { get; set; } public EntityInfo EntityInfo { get { return this.Context.EntityMaintenance.GetEntityInfo(); } } public int ExecuteCommand() { DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); var sql = DeleteBuilder.ToSqlString(); var paramters = DeleteBuilder.Parameters?.ToArray(); RestoreMapping(); AutoRemoveDataCache(); return Db.ExecuteCommand(sql, paramters); } public bool ExecuteCommandHasChange() { return ExecuteCommand() > 0; } public Task ExecuteCommandAsync() { var result = new Task(() => { var asyncDeleteable = CopyDeleteable(); return asyncDeleteable.ExecuteCommand(); }); TaskStart(result); return result; } public Task ExecuteCommandHasChangeAsync() { var result = new Task(() => { var asyncDeleteable = CopyDeleteable(); return asyncDeleteable.ExecuteCommand() > 0; }); TaskStart(result); return result; } public IDeleteable AS(string tableName) { var entityName = typeof(T).Name; IsAs = true; OldMappingTableList = this.Context.MappingTables; this.Context.MappingTables = this.Context.Utilities.TranslateCopy(this.Context.MappingTables); this.Context.MappingTables.Add(entityName, tableName); return this; ; } public IDeleteable Where(List deleteObjs) { if (deleteObjs == null || deleteObjs.Count() == 0) { Where(SqlBuilder.SqlFalse); return this; } var tableName = this.Context.EntityMaintenance.GetTableName(); var primaryFields = this.GetPrimaryKeys(); var isSinglePrimaryKey = primaryFields.Count == 1; Check.Exception(primaryFields.IsNullOrEmpty(), $"Table {tableName} with no primarykey"); if (isSinglePrimaryKey) { var primaryKeyValues = new List(); var primaryField = primaryFields.Single(); foreach (var deleteObj in deleteObjs) { var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName.Equals(entityPropertyName, StringComparison.CurrentCultureIgnoreCase)); var value = columnInfo.PropertyInfo.GetValue(deleteObj, null); primaryKeyValues.Add(value); } if (primaryKeyValues.Count < 10000) { var inValueString = primaryKeyValues.ToArray().ToJoinSqlInVals(); Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryFields.Single()), inValueString)); } else { if (DeleteBuilder.BigDataInValues == null) DeleteBuilder.BigDataInValues = new List(); DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues); DeleteBuilder.BigDataFiled = primaryField; } } else { var whereInSql = new StringBuilder(); foreach (var deleteObj in deleteObjs) { var orString = new StringBuilder(); var isFirst = deleteObjs.IndexOf(deleteObj) == 0; if (!isFirst) { orString.Append(DeleteBuilder.WhereInOrTemplate + UtilConstants.Space); } var i = 0; var andString = new StringBuilder(); foreach (var primaryField in primaryFields) { if (i != 0) andString.Append(DeleteBuilder.WhereInAndTemplate + UtilConstants.Space); var entityPropertyName = this.Context.EntityMaintenance.GetPropertyName(primaryField); var columnInfo = EntityInfo.Columns.Single(it => it.PropertyName == entityPropertyName); var entityValue = columnInfo.PropertyInfo.GetValue(deleteObj, null); andString.AppendFormat(DeleteBuilder.WhereInEqualTemplate, primaryField, entityValue); ++i; } orString.AppendFormat(DeleteBuilder.WhereInAreaTemplate, andString); whereInSql.Append(orString); } Where(string.Format(DeleteBuilder.WhereInAreaTemplate, whereInSql.ToString())); } return this; } public IDeleteable Where(Expression> expression) { var expResult = DeleteBuilder.GetExpressionValue(expression, ResolveExpressType.WhereSingle); DeleteBuilder.WhereInfos.Add(expResult.GetResultString()); return this; } public IDeleteable Where(T deleteObj) { Check.Exception(GetPrimaryKeys().IsNullOrEmpty(), "Where(entity) Primary key required"); Where(new List { deleteObj }); return this; } public IDeleteable Where(string whereString, object parameters = null) { DeleteBuilder.WhereInfos.Add(whereString); if (parameters != null) { if (DeleteBuilder.Parameters == null) { DeleteBuilder.Parameters = new List(); } DeleteBuilder.Parameters.AddRange(Context.Ado.GetParameters(parameters)); } return this; } public IDeleteable Where(string whereString, SugarParameter parameter) { DeleteBuilder.Parameters.Add(parameter); return this; } public IDeleteable Where(string whereString, SugarParameter[] parameters) { DeleteBuilder.Parameters.AddRange(parameters); return this; } public IDeleteable Where(string whereString, List parameters) { DeleteBuilder.Parameters.AddRange(parameters); return this; } public IDeleteable RemoveDataCache() { var cacheService = this.Context.CurrentConnectionConfig.ConfigureExternalServices.DataInfoCacheService; CacheSchemeMain.RemoveCache(cacheService, this.Context.EntityMaintenance.GetTableName()); return this; } public IDeleteable In(List primaryKeyValues) { if (primaryKeyValues == null || primaryKeyValues.Count() == 0) { Where(SqlBuilder.SqlFalse); return this; } return In(primaryKeyValues.ToArray()); } public IDeleteable In(PkType[] primaryKeyValues) { if (primaryKeyValues == null || primaryKeyValues.Count() == 0) { Where(SqlBuilder.SqlFalse); return this; } var tableName = this.Context.EntityMaintenance.GetTableName(); string primaryField = null; primaryField = GetPrimaryKeys().FirstOrDefault(); Check.ArgumentNullException(primaryField, "Table " + tableName + " with no primarykey"); if (primaryKeyValues.Length < 10000) { Where(string.Format(DeleteBuilder.WhereInTemplate, SqlBuilder.GetTranslationColumnName(primaryField), primaryKeyValues.ToJoinSqlInVals())); } else { if (DeleteBuilder.BigDataInValues == null) DeleteBuilder.BigDataInValues = new List(); DeleteBuilder.BigDataInValues.AddRange(primaryKeyValues.Select(it => (object)it)); DeleteBuilder.BigDataFiled = primaryField; } return this; } public IDeleteable In(PkType primaryKeyValue) { In(new PkType[] { primaryKeyValue }); return this; } public IDeleteable With(string lockString) { if (this.Context.CurrentConnectionConfig.DbType == DbType.SqlServer) DeleteBuilder.TableWithString = lockString; return this; } public KeyValuePair> ToSql() { DeleteBuilder.EntityInfo = this.Context.EntityMaintenance.GetEntityInfo(); var sql = DeleteBuilder.ToSqlString(); var paramters = DeleteBuilder.Parameters?.ToList(); RestoreMapping(); return new KeyValuePair>(sql, paramters); } private List GetPrimaryKeys() { if (this.Context.IsSystemTablesConfig) { return this.Context.DbMaintenance.GetPrimaries(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); } else { return this.EntityInfo.Columns.Where(it => it.IsPrimarykey).Select(it => it.DbColumnName).ToList(); } } protected virtual List GetIdentityKeys() { if (this.Context.IsSystemTablesConfig) { return this.Context.DbMaintenance.GetIsIdentities(this.Context.EntityMaintenance.GetTableName(this.EntityInfo.EntityName)); } else { return this.EntityInfo.Columns.Where(it => it.IsIdentity).Select(it => it.DbColumnName).ToList(); } } private void RestoreMapping() { if (IsAs) { this.Context.MappingTables = OldMappingTableList; } } private void TaskStart(Task result) { if (this.Context.CurrentConnectionConfig.IsShardSameThread) { Check.Exception(true, "IsShardSameThread=true can't be used async method"); } result.Start(); } private void AutoRemoveDataCache() { var moreSetts = this.Context.CurrentConnectionConfig.MoreSettings; var extService = this.Context.CurrentConnectionConfig.ConfigureExternalServices; if (moreSetts != null && moreSetts.IsAutoRemoveDataCache && extService != null && extService.DataInfoCacheService != null) { this.RemoveDataCache(); } } private IDeleteable CopyDeleteable() { var asyncContext = this.Context.Utilities.CopyContext(true); asyncContext.CurrentConnectionConfig.IsAutoCloseConnection = true; var asyncDeleteable = asyncContext.Deleteable(); var asyncDeleteBuilder = asyncDeleteable.DeleteBuilder; asyncDeleteBuilder.BigDataFiled = this.DeleteBuilder.BigDataFiled; asyncDeleteBuilder.BigDataInValues = this.DeleteBuilder.BigDataInValues; asyncDeleteBuilder.Parameters = this.DeleteBuilder.Parameters; asyncDeleteBuilder.sql = this.DeleteBuilder.sql; asyncDeleteBuilder.WhereInfos = this.DeleteBuilder.WhereInfos; asyncDeleteBuilder.TableWithString = this.DeleteBuilder.TableWithString; return asyncDeleteable; } } }