using System; using System.Collections.Generic; using System.Data.SqlTypes; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; namespace SqlSugar { public class SubInsertable : ISubInsertable where T : class, new() { internal EntityInfo Entity { get; set; } internal List SubList { get; set; } internal SqlSugarProvider Context { get; set; } internal T[] InsertObjects { get; set; } internal InsertBuilder InsertBuilder { get; set; } internal string Pk { get; set; } public ISubInsertable AddSubList(Expression> items) { if (this.SubList == null) this.SubList = new List(); this.SubList.Add(new SubInsertTreeExpression() { Expression = items }); return this; } public ISubInsertable AddSubList(Expression> tree) { try { var lamda = (tree as LambdaExpression); var memInit = lamda.Body as MemberInitExpression; if (memInit.Bindings != null) { MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0]; SubList.Add(new SubInsertTreeExpression() { Expression = memberAssignment.Expression, Childs = GetSubInsertTree(((MemberAssignment)memInit.Bindings[1]).Expression) }); } } catch { Check.Exception(true, tree.ToString() + " format error "); } return this; } private List GetSubInsertTree(Expression expression) { List resul = new List(); if (expression is ListInitExpression) { ListInitExpression exp = expression as ListInitExpression; foreach (var item in exp.Initializers) { SubInsertTreeExpression tree = new SubInsertTreeExpression(); var memInit = item.Arguments[0] as MemberInitExpression; if (memInit.Bindings != null) { MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0]; tree.Expression = memberAssignment.Expression; if (memInit.Bindings.Count > 1) { tree.Childs = GetSubInsertTree(((MemberAssignment)memInit.Bindings[1]).Expression); } } resul.Add(tree); } } else { } return resul; } [Obsolete("use ExecuteCommand")] public object ExecuteReturnPrimaryKey() { return ExecuteCommand(); } public async Task ExecuteCommandAsync() { object resut = 0; await Task.Run(() => { resut= ExecuteCommand(); }); return resut; } public object ExecuteCommand() { var isNoTrean = this.Context.Ado.Transaction == null; try { if (isNoTrean) this.Context.Ado.BeginTran(); var result = Execute(); if (isNoTrean) this.Context.Ado.CommitTran(); return result; } catch (Exception ex) { if (isNoTrean) this.Context.Ado.RollbackTran(); throw ex; } } private object Execute() { if (InsertObjects != null && InsertObjects.Count() > 0) { var isIdEntity = IsIdEntity(this.Entity); if (!isIdEntity) { this.Context.Insertable(InsertObjects).ExecuteCommand(); } foreach (var InsertObject in InsertObjects) { int id = 0; if (isIdEntity) { id = this.Context.Insertable(InsertObject).ExecuteReturnIdentity(); this.Entity.Columns.First(it => it.IsIdentity || it.OracleSequenceName.HasValue()).PropertyInfo.SetValue(InsertObject, id); } var pk = GetPrimaryKey(this.Entity, InsertObject, id); AddChildList(this.SubList, InsertObject, pk); } return InsertObjects.Count(); } else { return 0; } } [Obsolete("use ExecuteCommandAsync")] public Task ExecuteReturnPrimaryKeyAsync() { return Task.FromResult(ExecuteReturnPrimaryKey()); } private bool IsIdEntity(EntityInfo entity) { return entity.Columns.Where(it => it.IsIdentity||it.OracleSequenceName.HasValue()).Count() > 0; } private void AddChildList(List items, object insertObject, object pkValue) { if (items != null) { foreach (var item in items) { MemberExpression subMemberException; string subMemberName = GetMemberName(item, out subMemberException); string childName = GetChildName(item, subMemberException); var childListProperty = insertObject.GetType().GetProperty(childName); if (childListProperty == null) { childName = subMemberName; childListProperty = insertObject.GetType().GetProperty(childName); } var childList = childListProperty.GetValue(insertObject); if (childList != null) { if (!(childList is IEnumerable)) { childList = new List() { childList }; } if (!string.IsNullOrEmpty(subMemberName) &&subMemberName!=childName) { foreach (var child in childList as IEnumerable) { child.GetType().GetProperty(subMemberName).SetValue(child, pkValue); } } if (!(childList as IEnumerable).Any()) { continue; } var type = (childList as IEnumerable).First().GetType(); this.Context.InitMappingInfo(type); var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(type); var isIdentity = IsIdEntity(entityInfo); var tableName = entityInfo.DbTableName; List> insertList = new List>(); var entityList = (childList as IEnumerable).ToList(); foreach (var child in entityList) { insertList.Add(GetInsertDictionary(child, entityInfo)); } if (!isIdentity) { this.Context.Insertable(insertList).AS(tableName).ExecuteCommand(); } int i = 0; foreach (var insert in insertList) { int id = 0; if (isIdentity) { if (this.Context.CurrentConnectionConfig.DbType == DbType.PostgreSQL) { var sqlobj = this.Context.Insertable(insert).AS(tableName).ToSql(); id = this.Context.Ado.GetInt(sqlobj.Key+ " "+ this.InsertBuilder.Builder.GetTranslationColumnName(entityInfo.Columns.First(it=>isIdentity).DbColumnName), sqlobj.Value); } else { id = this.Context.Insertable(insert).AS(tableName).ExecuteReturnIdentity(); } if (this.Context.CurrentConnectionConfig.DbType == DbType.Oracle&&id==0) { var seqName=entityInfo.Columns.First(it => it.OracleSequenceName.HasValue())?.OracleSequenceName; id = this.Context.Ado.GetInt("select "+seqName+".currval from dual"); } } var entity = entityList[i]; var pk = GetPrimaryKey(entityInfo,entity, id); AddChildList(item.Childs, entity, pk); ++i; } } } } } private Dictionary GetInsertDictionary(object insetObject, EntityInfo subEntity) { Dictionary insertDictionary = new Dictionary(); foreach (var item in subEntity.Columns) { if (item.IsIdentity || item.IsIgnore) { } else if (!string.IsNullOrEmpty(item.OracleSequenceName) && this.Context.CurrentConnectionConfig.DbType == DbType.Oracle) { var value = "{SugarSeq:=}" + item.OracleSequenceName + ".nextval{SugarSeq:=}"; insertDictionary.Add(item.DbColumnName, value); continue; } else { var value = item.PropertyInfo.GetValue(insetObject); if (value == null&&this.Context.CurrentConnectionConfig.DbType==DbType.PostgreSQL) { var underType= UtilMethods.GetUnderType(item.PropertyInfo.PropertyType); if (underType == UtilConstants.DateType) { value = SqlDateTime.Null; } } insertDictionary.Add(item.DbColumnName, value); } } return insertDictionary; } private static string GetChildName(SubInsertTreeExpression item, MemberExpression subMemberException) { string childName; MemberExpression listMember = null; if (subMemberException.Expression is MethodCallExpression) { listMember = (subMemberException.Expression as MethodCallExpression).Arguments.First() as MemberExpression; } else { listMember = (subMemberException.Expression as MemberExpression); } if (listMember == null&& item.Expression is LambdaExpression) { listMember = (item.Expression as LambdaExpression).Body as MemberExpression; } if (listMember == null && item.Expression is MemberExpression) { listMember = item.Expression as MemberExpression; } childName = listMember.Member.Name; return childName; } private static string GetMemberName(SubInsertTreeExpression item, out MemberExpression subMemberException) { string subMemberName = null; Expression lambdaExpression; if (item.Expression is LambdaExpression) { lambdaExpression = (item.Expression as LambdaExpression).Body; } else { lambdaExpression = item.Expression; } if (lambdaExpression is UnaryExpression) { lambdaExpression = (lambdaExpression as UnaryExpression).Operand; } subMemberException = lambdaExpression as MemberExpression; subMemberName = subMemberException.Member.Name; return subMemberName; } private object GetPrimaryKey(EntityInfo entityInfo,object InsertObject, int id) { object pkValue; if (id.ObjToInt() == 0) { var primaryProperty = entityInfo.Columns.FirstOrDefault(it => it.IsPrimarykey); Check.Exception(primaryProperty == null, entityInfo.EntityName + " no primarykey"); pkValue = primaryProperty.PropertyInfo.GetValue(InsertObject); } else { pkValue = id; } return pkValue; } } }