using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public class Storageable : IStorageable where T : class, new() { SqlSugarProvider Context { get; set; } internal ISqlBuilder Builder; List Parameters; List> allDatas = new List>(); List dbDataList = new List(); List, bool>, string>> whereFuncs = new List, bool>, string>>(); Expression> whereExpression; Func formatTime; DbLockType? lockType; private string asname { get; set; } private bool isDisableFilters = false; public Storageable(List datas, SqlSugarProvider context) { this.Context = context; if (datas == null) datas = new List(); this.allDatas = datas.Select(it => new StorageableInfo() { Item = it }).ToList(); } Expression> queryableWhereExp; public IStorageable TableDataRange(Expression> exp) { this.queryableWhereExp = exp; return this; } public IStorageable SplitInsert(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Insert, conditions, message)); return this; } public IStorageable SplitDelete(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Delete, conditions, message)); return this; } public IStorageable SplitUpdate(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Update, conditions, message)); return this; } public IStorageable Saveable(string inserMessage = null,string updateMessage=null) { return this .SplitUpdate(it => it.Any(),updateMessage) .SplitInsert(it => true, inserMessage); } public IStorageable SplitError(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Error, conditions, message)); return this; } public IStorageable SplitIgnore(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Ignore, conditions, message)); return this; } public IStorageable DisableFilters() { this.isDisableFilters = true; return this; } public IStorageable TranLock(DbLockType dbLockType = DbLockType.Wait) { this.lockType = dbLockType; return this; } public IStorageable SplitOther(Func, bool> conditions, string message = null) { whereFuncs.Add(new KeyValuePair, bool>, string>(StorageType.Other, conditions, message)); return this; } public int ExecuteCommand() { var result = 0; var x = this.ToStorage(); result+=x.AsInsertable.ExecuteCommand(); var updateRow = x.AsUpdateable.ExecuteCommand(); if (updateRow < 0) updateRow = 0; result += updateRow; return result; } public async Task ExecuteCommandAsync() { var result = 0; var x = await this.ToStorageAsync(); result +=await x.AsInsertable.ExecuteCommandAsync(); result +=await x.AsUpdateable.ExecuteCommandAsync(); return result; } public StorageableResult ToStorage() { if (whereFuncs == null || whereFuncs.Count == 0) { return this.Saveable().ToStorage(); } if (this.allDatas.Count == 0) return new StorageableResult() { AsDeleteable = this.Context.Deleteable().AS(asname).Where(it => false), AsInsertable = this.Context.Insertable(new List()).AS(asname), AsUpdateable = this.Context.Updateable(new List()).AS(asname), InsertList = new List>(), UpdateList = new List>(), DeleteList = new List>(), ErrorList = new List>(), IgnoreList = new List>(), OtherList=new List>(), TotalList=new List>() }; var pkInfos = this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsPrimarykey); if (whereExpression==null&&!pkInfos.Any()) { Check.Exception(true, "Need primary key or WhereColumn"); } if (whereExpression == null && pkInfos.Any()) { this.Context.Utilities.PageEach(allDatas, 300, item => { var addItems=this.Context.Queryable().Filter(null, this.isDisableFilters).TranLock(this.lockType).AS(asname).WhereClassByPrimaryKey(item.Select(it => it.Item).ToList()).ToList(); dbDataList.AddRange(addItems); }); } var pkProperties = GetPkProperties(pkInfos); var messageList = allDatas.Select(it => new StorageableMessage() { Item = it.Item, Database = dbDataList, PkFields= pkProperties }).ToList(); foreach (var item in whereFuncs.OrderByDescending(it => (int)it.key)) { List> whereList = messageList.Where(it => it.StorageType == null).ToList(); Func, bool> exp = item.value1; var list = whereList.Where(exp).ToList(); foreach (var it in list) { it.StorageType = item.key; it.StorageMessage = item.value2; } } var delete = messageList.Where(it => it.StorageType == StorageType.Delete).ToList(); var update = messageList.Where(it => it.StorageType == StorageType.Update).ToList(); var inset = messageList.Where(it => it.StorageType == StorageType.Insert).ToList(); var error = messageList.Where(it => it.StorageType == StorageType.Error).ToList(); var ignore = messageList.Where(it => it.StorageType == StorageType.Ignore || it.StorageType == null).ToList(); var other = messageList.Where(it => it.StorageType == StorageType.Other).ToList(); StorageableResult result = new StorageableResult() { _WhereColumnList= wherecolumnList, _AsName =asname, _Context=this.Context, AsDeleteable = this.Context.Deleteable().AS(asname), AsUpdateable = this.Context.Updateable(update.Select(it => it.Item).ToList()).AS(asname), AsInsertable = this.Context.Insertable(inset.Select(it => it.Item).ToList()).AS(asname), OtherList = other, InsertList = inset, DeleteList = delete, UpdateList = update, ErrorList = error, IgnoreList = ignore, TotalList = messageList }; if (this.whereExpression != null) { result.AsUpdateable.WhereColumns(whereExpression); result.AsDeleteable.WhereColumns(update.Select(it => it.Item).ToList(),whereExpression); } result.AsDeleteable.Where(delete.Select(it => it.Item).ToList()); return result; } public async Task> ToStorageAsync() { if (whereFuncs == null || whereFuncs.Count == 0) { return await this.Saveable().ToStorageAsync(); } if (this.allDatas.Count == 0) return new StorageableResult() { AsDeleteable = this.Context.Deleteable().AS(asname).Where(it => false), AsInsertable = this.Context.Insertable(new List()).AS(asname), AsUpdateable = this.Context.Updateable(new List()).AS(asname), InsertList = new List>(), UpdateList = new List>(), DeleteList = new List>(), ErrorList = new List>(), IgnoreList = new List>(), OtherList = new List>(), TotalList = new List>() }; var pkInfos = this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsPrimarykey); if (whereExpression == null && !pkInfos.Any()) { Check.Exception(true, "Need primary key or WhereColumn"); } if (whereExpression == null && pkInfos.Any()) { await this.Context.Utilities.PageEachAsync(allDatas, 300,async item => { var addItems =await this.Context.Queryable().Filter(null,this.isDisableFilters).AS(asname).TranLock(this.lockType).WhereClassByPrimaryKey(item.Select(it => it.Item).ToList()).ToListAsync(); dbDataList.AddRange(addItems); }); } var pkProperties = GetPkProperties(pkInfos); var messageList = allDatas.Select(it => new StorageableMessage() { Item = it.Item, Database = dbDataList, PkFields = pkProperties }).ToList(); foreach (var item in whereFuncs.OrderByDescending(it => (int)it.key)) { List> whereList = messageList.Where(it => it.StorageType == null).ToList(); Func, bool> exp = item.value1; var list = whereList.Where(exp).ToList(); foreach (var it in list) { it.StorageType = item.key; it.StorageMessage = item.value2; } } var delete = messageList.Where(it => it.StorageType == StorageType.Delete).ToList(); var update = messageList.Where(it => it.StorageType == StorageType.Update).ToList(); var inset = messageList.Where(it => it.StorageType == StorageType.Insert).ToList(); var error = messageList.Where(it => it.StorageType == StorageType.Error).ToList(); var ignore = messageList.Where(it => it.StorageType == StorageType.Ignore || it.StorageType == null).ToList(); var other = messageList.Where(it => it.StorageType == StorageType.Other).ToList(); StorageableResult result = new StorageableResult() { _WhereColumnList = wherecolumnList, _AsName = asname, _Context = this.Context, AsDeleteable = this.Context.Deleteable().AS(asname), AsUpdateable = this.Context.Updateable(update.Select(it => it.Item).ToList()).AS(asname), AsInsertable = this.Context.Insertable(inset.Select(it => it.Item).ToList()).AS(asname), OtherList = other, InsertList = inset, DeleteList = delete, UpdateList = update, ErrorList = error, IgnoreList = ignore, TotalList = messageList }; if (this.whereExpression != null) { result.AsUpdateable.WhereColumns(whereExpression); result.AsDeleteable.WhereColumns(delete.Select(it => it.Item).ToList(),whereExpression); } result.AsDeleteable.Where(delete.Select(it => it.Item).ToList()); return result; } private string[] GetPkProperties(IEnumerable pkInfos) { if (whereExpression == null) { return pkInfos.Select(it => it.PropertyName).ToArray(); } else { return wherecolumnList.Select(it => it.PropertyName).ToArray(); } } List wherecolumnList; public IStorageable WhereColumns(Expression> columns, Func formatTime) { this.formatTime = formatTime; return WhereColumns(columns); } public IStorageable WhereColumns(Expression> columns) { if (columns == null) return this; else { List list = GetExpressionValue(columns, ResolveExpressType.ArraySingle).GetResultArray().Select(it => Builder.GetNoTranslationColumnName(it)).ToList(); var dbColumns = this.Context.EntityMaintenance.GetEntityInfo().Columns.Where(it => it.IsIgnore == false); var whereColumns = dbColumns.Where(it => list.Any(y => it.DbColumnName.Equals(y, StringComparison.CurrentCultureIgnoreCase) || it.PropertyName.Equals(y, StringComparison.CurrentCultureIgnoreCase)) ).ToList(); wherecolumnList = whereColumns; if (whereColumns.Count == 0) { whereColumns = dbColumns.Where(it => it.IsPrimarykey).ToList(); } if (whereColumns.Count > 0) { if (queryableWhereExp == null) { this.Context.Utilities.PageEach(allDatas, 200, itemList => { List conditList = new List(); SetConditList(itemList, whereColumns, conditList); var addItem = this.Context.Queryable().AS(asname).Where(conditList).ToList(); this.dbDataList.AddRange(addItem); }); } else { this.dbDataList.AddRange(this.Context.Queryable().AS(asname).Where(queryableWhereExp).ToList()); } } this.whereExpression = columns; return this; } } public IStorageable WhereColumns(string [] columns) { var list = columns.Select(it=>this.Context.EntityMaintenance.GetPropertyName(it)).ToList(); var exp=ExpressionBuilderHelper.CreateNewFields(this.Context.EntityMaintenance.GetEntityInfo(), list); return this.WhereColumns(exp); } public IStorageable WhereColumns(string[] columns, Func formatTime) { this.formatTime = formatTime; return WhereColumns(columns); } private void SetConditList(List> itemList, List whereColumns, List conditList) { ; foreach (var dataItem in itemList) { var condition = new ConditionalCollections() { ConditionalList = new List>() }; conditList.Add(condition); int i = 0; foreach (var item in whereColumns) { var value = item.PropertyInfo.GetValue(dataItem.Item, null); if (value != null&&value.GetType().IsEnum()) { if (this.Context.CurrentConnectionConfig.MoreSettings?.TableEnumIsString == true) { value = value.ToString(); } else { value = Convert.ToInt64(value); } } condition.ConditionalList.Add(new KeyValuePair(i==0?WhereType.Or :WhereType.And, new ConditionalModel() { FieldName = item.DbColumnName, ConditionalType = ConditionalType.Equal, CSharpTypeName=UtilMethods.GetTypeName(value), FieldValue = value==null?"null":value.ObjToString(formatTime), FieldValueConvertFunc=this.Context.CurrentConnectionConfig.DbType==DbType.PostgreSQL? UtilMethods.GetTypeConvert(value):null })); ++i; } } } public virtual ExpressionResult GetExpressionValue(Expression expression, ResolveExpressType resolveType) { ILambdaExpressions resolveExpress = InstanceFactory.GetLambdaExpressions(this.Context.CurrentConnectionConfig); ; if (this.Context.CurrentConnectionConfig.MoreSettings != null) { resolveExpress.TableEnumIsString = this.Context.CurrentConnectionConfig.MoreSettings.TableEnumIsString; resolveExpress.PgSqlIsAutoToLower = this.Context.CurrentConnectionConfig.MoreSettings.PgSqlIsAutoToLower; } else { resolveExpress.PgSqlIsAutoToLower = true; } 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.Resolve(expression, resolveType); if (this.Parameters == null) this.Parameters = new List(); this.Parameters.AddRange(resolveExpress.Parameters); var result = resolveExpress.Result; return result; } public IStorageable As(string tableName) { this.asname = tableName; return this; } } }