diff --git a/Src/Asp.Net/SqlServerTest/Demo/Demo3_Insertable.cs b/Src/Asp.Net/SqlServerTest/Demo/Demo3_Insertable.cs index 6153f188e..bebf51dee 100644 --- a/Src/Asp.Net/SqlServerTest/Demo/Demo3_Insertable.cs +++ b/Src/Asp.Net/SqlServerTest/Demo/Demo3_Insertable.cs @@ -56,7 +56,13 @@ namespace OrmTest }; db.Insertable(insertObjs).UseSqlServer().ExecuteBlueCopy(); - db.CodeFirst.InitTables(); + db.CodeFirst.InitTables(); + db.CodeFirst.InitTables(); + db.DbMaintenance.TruncateTable("RootTable0"); + db.DbMaintenance.TruncateTable("TwoItem"); + db.DbMaintenance.TruncateTable("TwoItem2"); + db.DbMaintenance.TruncateTable("TwoItem3"); + db.DbMaintenance.TruncateTable("ThreeItem2"); Console.WriteLine("SubInsert Start"); db.Insertable(new Order() @@ -72,41 +78,72 @@ namespace OrmTest OrderId=0, Price=1, ItemId=1 + }, + new OrderItem(){ + CreateTime=DateTime.Now, + OrderId=0, + Price=2, + ItemId=2 } } }) .AddSubList(it => it.Items.First().OrderId).ExecuteReturnPrimaryKey(); - db.Insertable(new List() { - new SubInsertTest() + + + db.Insertable(new List() { + new RootTable0() { Name="aa", - SubInsertTestItem1=new SubInsertTestItem1() { - a="nn" - }, - SubInsertTestItem=new SubInsertTestItem() + TwoItem2=new TwoItem2() { + Id="1", + ThreeItem2=new List(){ + new ThreeItem2(){ Name="a", TwoItem2Id="1" } + } + }, + TwoItem=new TwoItem() { - Name ="item" , - TestId=2 + Name ="itema" , + RootId=2 + }, + TwoItem3=new List(){ + new TwoItem3(){ Id=0, Name="a",Desc="" }, + } }, - new SubInsertTest() + new RootTable0() { - Name="aa", - SubInsertTestItem1=new SubInsertTestItem1() { - a="nn" + Name="bb", + TwoItem2=new TwoItem2() { + Id="2" }, - SubInsertTestItem=new SubInsertTestItem() + TwoItem=new TwoItem() { - Name ="item" , - TestId=2 + Name ="itemb" , + RootId=2, + + }, + TwoItem3=new List(){ + new TwoItem3(){ Id=1, Name="b",Desc="" }, + new TwoItem3(){ Id=2, Name="b1",Desc="1" }, } } }) - .AddSubList(it => it.SubInsertTestItem.TestId) - .AddSubList(it => it.SubInsertTestItem1) - .ExecuteReturnPrimaryKey(); - + .AddSubList(it => it.TwoItem.RootId) + .AddSubList(it => new GetSubInsertTree() + { + Expression = it.TwoItem2.RootId, + ChildExpression=new List() { + new GetSubInsertTree(){ + Expression=it.TwoItem2.ThreeItem2.First().TwoItem2Id + } + } + }) + .AddSubList(it => it.TwoItem3) + .ExecuteReturnPrimaryKey(); + + + Console.WriteLine("#### Insertable End ####"); } diff --git a/Src/Asp.Net/SqlServerTest/Models/SubInsertTest.cs b/Src/Asp.Net/SqlServerTest/Models/SubInsertTest.cs index 41fe5d982..6f93b566e 100644 --- a/Src/Asp.Net/SqlServerTest/Models/SubInsertTest.cs +++ b/Src/Asp.Net/SqlServerTest/Models/SubInsertTest.cs @@ -6,34 +6,47 @@ using System.Threading.Tasks; namespace OrmTest { - public class SubInsertTest + public class RootTable0 { [SqlSugar.SugarColumn(IsPrimaryKey =true,IsIdentity =true)] public int Id { get; set; } public string Name { get; set; } [SqlSugar.SugarColumn(IsIgnore =true)] - public SubInsertTestItem SubInsertTestItem { get; set; } + public TwoItem TwoItem { get; set; } [SqlSugar.SugarColumn(IsIgnore = true)] - public SubInsertTestItem1 SubInsertTestItem1 { get; set; } + public TwoItem2 TwoItem2 { get; set; } [SqlSugar.SugarColumn(IsIgnore = true)] - public List SubInsertTestItem2 { get; set; } + public List TwoItem3 { get; set; } } - public class SubInsertTestItem + public class TwoItem { [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } - public int TestId { get; set; } + public int RootId { get; set; } public string Name { get; set; } } - public class SubInsertTestItem1 + public class TwoItem2 { - public string a { get; set; } + [SqlSugar.SugarColumn(IsPrimaryKey = true)] + public string Id { get; set; } + public int RootId { get; set; } + [SqlSugar.SugarColumn(IsIgnore =true)] + public List ThreeItem2 { get; set; } } - public class SubInsertTestItem2 + public class TwoItem3 { - public int OrderId { get; set; } - public int xid { get; set; } - public string a { get; set; } + [SqlSugar.SugarColumn(IsPrimaryKey = true)] + public int Id { get; set; } + public string Name { get; set; } + public string Desc { get; set; } + } + public class ThreeItem2 + { + [SqlSugar.SugarColumn(IsPrimaryKey = true)] + + public int Id { get; set; } + public string Name { get; set; } + public string TwoItem2Id { get; set; } } } diff --git a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs index 195c8d920..8d45a9d4b 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/InsertableProvider.cs @@ -262,21 +262,21 @@ namespace SqlSugar { return new SubInsertable(); } - string subMemberName; - object sublist; SubInsertable result = new SubInsertable(); - result.GetList(this.InsertObjs,items, out subMemberName, out sublist); result.InsertObjects = this.InsertObjs; result.Context = this.Context; - result.SubList = new Dictionary(); - result.SubList.Add(subMemberName, sublist); + result.SubList = new List(); + result.SubList.Add(new SubInsertTreeExpression() { Expression= items }); result.InsertBuilder = this.InsertBuilder; result.Pk = GetPrimaryKeys().First(); result.Entity = this.EntityInfo; return result; } + public ISubInsertable AddSubList(Expression> tree) + { + return null; + } - #endregion #region Protected Methods diff --git a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/SubInserable.cs b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/SubInserable.cs index e40e1f84f..d91352e05 100644 --- a/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/SubInserable.cs +++ b/Src/Asp.Net/SqlSugar/Abstract/InsertableProvider/SubInserable.cs @@ -10,176 +10,180 @@ namespace SqlSugar public class SubInsertable : ISubInsertable where T : class, new() { internal EntityInfo Entity { get; set; } - internal Dictionary SubList { get; set; } + internal List SubList { get; set; } internal SqlSugarProvider Context { get; set; } - internal T [] InsertObjects { get; set; } + internal T[] InsertObjects { get; set; } internal InsertBuilder InsertBuilder { get; set; } internal string Pk { get; set; } public ISubInsertable AddSubList(Expression> items) { - if (InsertObjects != null&&InsertObjects.Count() > 0) + if (this.SubList == null) + this.SubList = new List(); + this.SubList.Add(new SubInsertTreeExpression() { Expression = items }); + return this; + } + public ISubInsertable AddSubList(Expression> tree) + { + var lamda = (tree as LambdaExpression); + var memInit = lamda.Body as MemberInitExpression; + if (memInit.Bindings != null) { - string subMemberName; - object sublist; - GetList(InsertObjects, items, out subMemberName, out sublist); - if (!this.SubList.ContainsKey(subMemberName)) - { - this.SubList.Add(subMemberName, sublist); - } + + MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0]; + SubList.Add(new SubInsertTreeExpression() { + Expression= memberAssignment.Expression, + Childs= GetSubInsertTree(((MemberAssignment)memInit.Bindings[1]).Expression) + }); } return this; } - public object ExecuteReturnPrimaryKey() + private List GetSubInsertTree(Expression expression) { - - if (InsertObjects != null && InsertObjects.Count()>0) + List resul = new List(); + + if (expression is ListInitExpression) { - int count = 1; - foreach (var InsertObject in InsertObjects) + ListInitExpression exp = expression as ListInitExpression; + foreach (var item in exp.Initializers) { - List conModel = new List(); - int id = this.Context.Insertable(InsertObject).ExecuteReturnIdentity(); - object pkValue = null; - var qureyable = this.Context.Queryable(); - if (id.ObjToInt() == 0) + SubInsertTreeExpression tree = new SubInsertTreeExpression(); + var memInit = item.Arguments[0] as MemberInitExpression; + if (memInit.Bindings != null) { - var primaryProperty = this.Entity.Columns.FirstOrDefault(it => - it.PropertyName.Equals(this.Pk, StringComparison.CurrentCultureIgnoreCase) || - it.DbColumnName.Equals(this.Pk, StringComparison.CurrentCultureIgnoreCase) - ); - pkValue = primaryProperty.PropertyInfo.GetValue(InsertObject); - qureyable.In(pkValue); - } - else - { - qureyable.In(id); - pkValue = id; - } - var data = qureyable.First(); - foreach (var item in this.SubList) - { - - Dictionary insertDictionary = new Dictionary(); - if (item.Value == null) - { - continue; - } - EntityInfo subEntity = null; - if (item.Value is IEnumerable) - { - var list = item.Value as IEnumerable; - if (list.Count() == 0) - { - continue; - } - var type = list.First().GetType(); - this.Context.InitMappingInfo(type); - subEntity = this.Context.EntityMaintenance.GetEntityInfo(type); - foreach (var sbItem in list) - { - SetItems(insertDictionary, sbItem, subEntity, item.Key, pkValue); - } - } - else if (item.Value.GetType().IsClass()) - { - var type = item.Value.GetType(); - this.Context.InitMappingInfo(type); - subEntity = this.Context.EntityMaintenance.GetEntityInfo(type); - SetItems(insertDictionary, item.Value, subEntity, item.Key, pkValue); - } - count += this.Context.Insertable(insertDictionary).AS(subEntity.DbTableName).ExecuteCommand(); + MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0]; + tree.Expression = memberAssignment.Expression; } + resul.Add(tree); } - return count; } else { - return 0; + } - + return resul; } - public async Task ExecuteReturnPrimaryKeyAsync() + + public object ExecuteReturnPrimaryKey() { if (InsertObjects != null && InsertObjects.Count() > 0) { - int count = 1; + var isIdEntity = IsIdEntity(this.Entity); + if (!isIdEntity) + { + this.Context.Insertable(InsertObjects).ExecuteCommand(); + } foreach (var InsertObject in InsertObjects) { - List conModel = new List(); - int id = await this.Context.Insertable(InsertObject).ExecuteReturnIdentityAsync(); - object pkValue = null; - var qureyable = this.Context.Queryable(); - if (id.ObjToInt() == 0) + int id = 0; + if (isIdEntity) { - var primaryProperty = this.Entity.Columns.FirstOrDefault(it => - it.PropertyName.Equals(this.Pk, StringComparison.CurrentCultureIgnoreCase) || - it.DbColumnName.Equals(this.Pk, StringComparison.CurrentCultureIgnoreCase) - ); - pkValue = primaryProperty.PropertyInfo.GetValue(InsertObject); - qureyable.In(pkValue); - } - else - { - qureyable.In(id); - pkValue = id; - } - var data =await qureyable.FirstAsync(); - foreach (var item in this.SubList) - { - - Dictionary insertDictionary = new Dictionary(); - if (item.Value == null) - { - continue; - } - EntityInfo subEntity = null; - if (item.Value is IEnumerable) - { - var list = item.Value as IEnumerable; - if (list.Count() == 0) - { - continue; - } - var type = list.First().GetType(); - this.Context.InitMappingInfo(type); - subEntity = this.Context.EntityMaintenance.GetEntityInfo(type); - foreach (var sbItem in list) - { - SetItems(insertDictionary, sbItem, subEntity, item.Key, pkValue); - } - } - else if (item.Value.GetType().IsClass()) - { - var type = item.Value.GetType(); - this.Context.InitMappingInfo(type); - subEntity = this.Context.EntityMaintenance.GetEntityInfo(type); - SetItems(insertDictionary, item.Value, subEntity, item.Key, pkValue); - } - count +=await this.Context.Insertable(insertDictionary).AS(subEntity.DbTableName).ExecuteCommandAsync(); + id = this.Context.Insertable(InsertObject).ExecuteReturnIdentity(); } + var pk = GetPrimaryKey(this.Entity,InsertObject, id); + AddChildList(this.SubList, InsertObject, pk); } - return count; + return InsertObjects.Count(); } else { return 0; } - } - public void GetList(T[] inserts,Expression> items, out string subMemberName, out object sublist) + + public Task ExecuteReturnPrimaryKeyAsync() { - var lambdaExpression = (items as LambdaExpression).Body; - if (lambdaExpression is UnaryExpression) + return Task.FromResult(ExecuteReturnPrimaryKey()); + } + + private bool IsIdEntity(EntityInfo entity) + { + return entity.Columns.Where(it => it.IsIdentity).Count() > 0; + } + + private void AddChildList(List items, object insertObject, object pkValue) + { + if (items != null) { - lambdaExpression = (lambdaExpression as UnaryExpression).Operand; + foreach (var item in items) + { + MemberExpression subMemberException; + string subMemberName = GetMemberName(item, out subMemberException); + string childName = GetChildName(item, subMemberException); + var childList = insertObject.GetType().GetProperty(childName).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); + } + } + 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) + { + id = this.Context.Insertable(insert).AS(tableName).ExecuteReturnIdentity(); + } + var entity = entityList[i]; + var pk = GetPrimaryKey(entityInfo,entity, id); + AddChildList(item.Childs, entity, pk); + ++i; + } + } + } } - MemberExpression subMemberException = lambdaExpression as MemberExpression; - subMemberName = subMemberException.Member.Name; + } + 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 + { + insertDictionary.Add(item.DbColumnName, item.PropertyInfo.GetValue(insetObject)); + } + } + return insertDictionary; + } + private static string GetChildName(SubInsertTreeExpression item, MemberExpression subMemberException) + { + string childName; MemberExpression listMember = null; - sublist = null; if (subMemberException.Expression is MethodCallExpression) { listMember = (subMemberException.Expression as MethodCallExpression).Arguments.First() as MemberExpression; @@ -191,32 +195,47 @@ namespace SqlSugar } if (listMember == null) { - listMember = (items as LambdaExpression).Body as MemberExpression; - subMemberName = Guid.NewGuid().ToString(); + listMember = (item.Expression as LambdaExpression).Body as MemberExpression; } - sublist = inserts.First().GetType().GetProperty(listMember.Member.Name).GetValue(inserts.First()); + childName = listMember.Member.Name; + return childName; } - private void SetItems(Dictionary insertDictionary, object sbItem, EntityInfo subEntity,string key,object pkValue) + + private static string GetMemberName(SubInsertTreeExpression item, out MemberExpression subMemberException) { - foreach (var item in subEntity.Columns) + string subMemberName = null; + Expression lambdaExpression; + if (item.Expression is LambdaExpression) { - if (item.IsIdentity||item.IsIgnore) - continue; - if (!string.IsNullOrEmpty(item.OracleSequenceName)&&this.Context.CurrentConnectionConfig.DbType==DbType.Oracle) - { - var value = "{SugarSeq:=}"+item.OracleSequenceName+ ".nextval{SugarSeq:=}"; - insertDictionary.Add(item.DbColumnName, value); - continue; - } - if (item.PropertyInfo.Name == key) - { - insertDictionary.Add(item.DbColumnName, pkValue); - } - else - { - insertDictionary.Add(item.DbColumnName, item.PropertyInfo.GetValue(sbItem)); - } + 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); + pkValue = primaryProperty.PropertyInfo.GetValue(InsertObject); + } + else + { + pkValue = id; + } + + return pkValue; } } } diff --git a/Src/Asp.Net/SqlSugar/Entities/SubInsertTree.cs b/Src/Asp.Net/SqlSugar/Entities/SubInsertTree.cs new file mode 100644 index 000000000..961e6b63d --- /dev/null +++ b/Src/Asp.Net/SqlSugar/Entities/SubInsertTree.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Text; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class GetSubInsertTree + { + public object Expression { get; set; } + public List ChildExpression { get; set; } + } + + internal class SubInsertTreeExpression + { + public Expression Expression { get; set; } + public List Childs { get; set; } + } +} diff --git a/Src/Asp.Net/SqlSugar/Interface/ISubInsertable.cs b/Src/Asp.Net/SqlSugar/Interface/ISubInsertable.cs index 70c75ffc9..b93d92414 100644 --- a/Src/Asp.Net/SqlSugar/Interface/ISubInsertable.cs +++ b/Src/Asp.Net/SqlSugar/Interface/ISubInsertable.cs @@ -6,6 +6,7 @@ namespace SqlSugar public interface ISubInsertable { ISubInsertable AddSubList(Expression> items); + ISubInsertable AddSubList(Expression> tree); object ExecuteReturnPrimaryKey(); } } \ No newline at end of file diff --git a/Src/Asp.Net/SqlSugar/Interface/Insertable.cs b/Src/Asp.Net/SqlSugar/Interface/Insertable.cs index b49e64f0c..f362f6864 100644 --- a/Src/Asp.Net/SqlSugar/Interface/Insertable.cs +++ b/Src/Asp.Net/SqlSugar/Interface/Insertable.cs @@ -29,7 +29,8 @@ namespace SqlSugar IInsertable IgnoreColumns(params string[]columns); IInsertable IgnoreColumns(bool ignoreNullColumn, bool isOffIdentity = false); - ISubInsertable AddSubList(Expression> SubForeignKey); + ISubInsertable AddSubList(Expression> subForeignKey); + ISubInsertable AddSubList(Expression> tree); IInsertable EnableDiffLogEvent(object businessData = null); IInsertable RemoveDataCache(); diff --git a/Src/Asp.Net/SqlSugar/SqlSugar.csproj b/Src/Asp.Net/SqlSugar/SqlSugar.csproj index 9859ed151..eba54bc29 100644 --- a/Src/Asp.Net/SqlSugar/SqlSugar.csproj +++ b/Src/Asp.Net/SqlSugar/SqlSugar.csproj @@ -88,6 +88,7 @@ +