Update SubInsert

This commit is contained in:
skx 2020-11-13 21:36:52 +08:00
parent fe638adf37
commit cdce78f067
8 changed files with 282 additions and 189 deletions

View File

@ -56,7 +56,13 @@ namespace OrmTest
}; };
db.Insertable(insertObjs).UseSqlServer().ExecuteBlueCopy(); db.Insertable(insertObjs).UseSqlServer().ExecuteBlueCopy();
db.CodeFirst.InitTables<SubInsertTest, SubInsertTestItem, SubInsertTestItem1, SubInsertTestItem2>(); db.CodeFirst.InitTables<RootTable0, TwoItem, TwoItem2, TwoItem3>();
db.CodeFirst.InitTables<ThreeItem2>();
db.DbMaintenance.TruncateTable("RootTable0");
db.DbMaintenance.TruncateTable("TwoItem");
db.DbMaintenance.TruncateTable("TwoItem2");
db.DbMaintenance.TruncateTable("TwoItem3");
db.DbMaintenance.TruncateTable("ThreeItem2");
Console.WriteLine("SubInsert Start"); Console.WriteLine("SubInsert Start");
db.Insertable(new Order() db.Insertable(new Order()
@ -72,41 +78,72 @@ namespace OrmTest
OrderId=0, OrderId=0,
Price=1, Price=1,
ItemId=1 ItemId=1
},
new OrderItem(){
CreateTime=DateTime.Now,
OrderId=0,
Price=2,
ItemId=2
} }
} }
}) })
.AddSubList(it => it.Items.First().OrderId).ExecuteReturnPrimaryKey(); .AddSubList(it => it.Items.First().OrderId).ExecuteReturnPrimaryKey();
db.Insertable(new List<SubInsertTest>() {
new SubInsertTest()
db.Insertable(new List<RootTable0>() {
new RootTable0()
{ {
Name="aa", Name="aa",
SubInsertTestItem1=new SubInsertTestItem1() { TwoItem2=new TwoItem2() {
a="nn" Id="1",
}, ThreeItem2=new List<ThreeItem2>(){
SubInsertTestItem=new SubInsertTestItem() new ThreeItem2(){ Name="a", TwoItem2Id="1" }
}
},
TwoItem=new TwoItem()
{ {
Name ="item" , Name ="itema" ,
TestId=2 RootId=2
},
TwoItem3=new List<TwoItem3>(){
new TwoItem3(){ Id=0, Name="a",Desc="" },
} }
}, },
new SubInsertTest() new RootTable0()
{ {
Name="aa", Name="bb",
SubInsertTestItem1=new SubInsertTestItem1() { TwoItem2=new TwoItem2() {
a="nn" Id="2"
}, },
SubInsertTestItem=new SubInsertTestItem() TwoItem=new TwoItem()
{ {
Name ="item" , Name ="itemb" ,
TestId=2 RootId=2,
},
TwoItem3=new List<TwoItem3>(){
new TwoItem3(){ Id=1, Name="b",Desc="" },
new TwoItem3(){ Id=2, Name="b1",Desc="1" },
} }
} }
}) })
.AddSubList(it => it.SubInsertTestItem.TestId) .AddSubList(it => it.TwoItem.RootId)
.AddSubList(it => it.SubInsertTestItem1) .AddSubList(it => new GetSubInsertTree()
.ExecuteReturnPrimaryKey(); {
Expression = it.TwoItem2.RootId,
ChildExpression=new List<GetSubInsertTree>() {
new GetSubInsertTree(){
Expression=it.TwoItem2.ThreeItem2.First().TwoItem2Id
}
}
})
.AddSubList(it => it.TwoItem3)
.ExecuteReturnPrimaryKey();
Console.WriteLine("#### Insertable End ####"); Console.WriteLine("#### Insertable End ####");
} }

View File

@ -6,34 +6,47 @@ using System.Threading.Tasks;
namespace OrmTest namespace OrmTest
{ {
public class SubInsertTest public class RootTable0
{ {
[SqlSugar.SugarColumn(IsPrimaryKey =true,IsIdentity =true)] [SqlSugar.SugarColumn(IsPrimaryKey =true,IsIdentity =true)]
public int Id { get; set; } public int Id { get; set; }
public string Name { get; set; } public string Name { get; set; }
[SqlSugar.SugarColumn(IsIgnore =true)] [SqlSugar.SugarColumn(IsIgnore =true)]
public SubInsertTestItem SubInsertTestItem { get; set; } public TwoItem TwoItem { get; set; }
[SqlSugar.SugarColumn(IsIgnore = true)] [SqlSugar.SugarColumn(IsIgnore = true)]
public SubInsertTestItem1 SubInsertTestItem1 { get; set; } public TwoItem2 TwoItem2 { get; set; }
[SqlSugar.SugarColumn(IsIgnore = true)] [SqlSugar.SugarColumn(IsIgnore = true)]
public List<SubInsertTestItem2> SubInsertTestItem2 { get; set; } public List<TwoItem3> TwoItem3 { get; set; }
} }
public class SubInsertTestItem public class TwoItem
{ {
[SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)] [SqlSugar.SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
public int Id { get; set; } public int Id { get; set; }
public int TestId { get; set; } public int RootId { get; set; }
public string Name { 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> ThreeItem2 { get; set; }
} }
public class SubInsertTestItem2 public class TwoItem3
{ {
public int OrderId { get; set; } [SqlSugar.SugarColumn(IsPrimaryKey = true)]
public int xid { get; set; } public int Id { get; set; }
public string a { 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; }
} }
} }

View File

@ -262,21 +262,21 @@ namespace SqlSugar
{ {
return new SubInsertable<T>(); return new SubInsertable<T>();
} }
string subMemberName;
object sublist;
SubInsertable<T> result = new SubInsertable<T>(); SubInsertable<T> result = new SubInsertable<T>();
result.GetList(this.InsertObjs,items, out subMemberName, out sublist);
result.InsertObjects = this.InsertObjs; result.InsertObjects = this.InsertObjs;
result.Context = this.Context; result.Context = this.Context;
result.SubList = new Dictionary<string, object>(); result.SubList = new List<SubInsertTreeExpression>();
result.SubList.Add(subMemberName, sublist); result.SubList.Add(new SubInsertTreeExpression() { Expression= items });
result.InsertBuilder = this.InsertBuilder; result.InsertBuilder = this.InsertBuilder;
result.Pk = GetPrimaryKeys().First(); result.Pk = GetPrimaryKeys().First();
result.Entity = this.EntityInfo; result.Entity = this.EntityInfo;
return result; return result;
} }
public ISubInsertable<T> AddSubList(Expression<Func<T, GetSubInsertTree>> tree)
{
return null;
}
#endregion #endregion
#region Protected Methods #region Protected Methods

View File

@ -10,176 +10,180 @@ namespace SqlSugar
public class SubInsertable<T> : ISubInsertable<T> where T : class, new() public class SubInsertable<T> : ISubInsertable<T> where T : class, new()
{ {
internal EntityInfo Entity { get; set; } internal EntityInfo Entity { get; set; }
internal Dictionary<string, object> SubList { get; set; } internal List<SubInsertTreeExpression> SubList { get; set; }
internal SqlSugarProvider Context { get; set; } internal SqlSugarProvider Context { get; set; }
internal T [] InsertObjects { get; set; } internal T[] InsertObjects { get; set; }
internal InsertBuilder InsertBuilder { get; set; } internal InsertBuilder InsertBuilder { get; set; }
internal string Pk { get; set; } internal string Pk { get; set; }
public ISubInsertable<T> AddSubList(Expression<Func<T, object>> items) public ISubInsertable<T> AddSubList(Expression<Func<T, object>> items)
{ {
if (InsertObjects != null&&InsertObjects.Count() > 0) if (this.SubList == null)
this.SubList = new List<SubInsertTreeExpression>();
this.SubList.Add(new SubInsertTreeExpression() { Expression = items });
return this;
}
public ISubInsertable<T> AddSubList(Expression<Func<T, GetSubInsertTree>> tree)
{
var lamda = (tree as LambdaExpression);
var memInit = lamda.Body as MemberInitExpression;
if (memInit.Bindings != null)
{ {
string subMemberName;
object sublist; MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0];
GetList(InsertObjects, items, out subMemberName, out sublist); SubList.Add(new SubInsertTreeExpression() {
if (!this.SubList.ContainsKey(subMemberName)) Expression= memberAssignment.Expression,
{ Childs= GetSubInsertTree(((MemberAssignment)memInit.Bindings[1]).Expression)
this.SubList.Add(subMemberName, sublist); });
}
} }
return this; return this;
} }
public object ExecuteReturnPrimaryKey() private List<SubInsertTreeExpression> GetSubInsertTree(Expression expression)
{ {
List<SubInsertTreeExpression> resul = new List<SubInsertTreeExpression>();
if (InsertObjects != null && InsertObjects.Count()>0)
if (expression is ListInitExpression)
{ {
int count = 1; ListInitExpression exp = expression as ListInitExpression;
foreach (var InsertObject in InsertObjects) foreach (var item in exp.Initializers)
{ {
List<ConditionalModel> conModel = new List<ConditionalModel>(); SubInsertTreeExpression tree = new SubInsertTreeExpression();
int id = this.Context.Insertable(InsertObject).ExecuteReturnIdentity(); var memInit = item.Arguments[0] as MemberInitExpression;
object pkValue = null; if (memInit.Bindings != null)
var qureyable = this.Context.Queryable<T>();
if (id.ObjToInt() == 0)
{ {
var primaryProperty = this.Entity.Columns.FirstOrDefault(it => MemberAssignment memberAssignment = (MemberAssignment)memInit.Bindings[0];
it.PropertyName.Equals(this.Pk, StringComparison.CurrentCultureIgnoreCase) || tree.Expression = memberAssignment.Expression;
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<string, object> insertDictionary = new Dictionary<string, object>();
if (item.Value == null)
{
continue;
}
EntityInfo subEntity = null;
if (item.Value is IEnumerable<object>)
{
var list = item.Value as IEnumerable<object>;
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();
} }
resul.Add(tree);
} }
return count;
} }
else else
{ {
return 0;
} }
return resul;
} }
public async Task<object> ExecuteReturnPrimaryKeyAsync()
public object ExecuteReturnPrimaryKey()
{ {
if (InsertObjects != null && InsertObjects.Count() > 0) 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) foreach (var InsertObject in InsertObjects)
{ {
List<ConditionalModel> conModel = new List<ConditionalModel>(); int id = 0;
int id = await this.Context.Insertable(InsertObject).ExecuteReturnIdentityAsync(); if (isIdEntity)
object pkValue = null;
var qureyable = this.Context.Queryable<T>();
if (id.ObjToInt() == 0)
{ {
var primaryProperty = this.Entity.Columns.FirstOrDefault(it => id = this.Context.Insertable(InsertObject).ExecuteReturnIdentity();
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<string, object> insertDictionary = new Dictionary<string, object>();
if (item.Value == null)
{
continue;
}
EntityInfo subEntity = null;
if (item.Value is IEnumerable<object>)
{
var list = item.Value as IEnumerable<object>;
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();
} }
var pk = GetPrimaryKey(this.Entity,InsertObject, id);
AddChildList(this.SubList, InsertObject, pk);
} }
return count; return InsertObjects.Count();
} }
else else
{ {
return 0; return 0;
} }
} }
public void GetList(T[] inserts,Expression<Func<T, object>> items, out string subMemberName, out object sublist)
public Task<object> ExecuteReturnPrimaryKeyAsync()
{ {
var lambdaExpression = (items as LambdaExpression).Body; return Task.FromResult(ExecuteReturnPrimaryKey());
if (lambdaExpression is UnaryExpression) }
private bool IsIdEntity(EntityInfo entity)
{
return entity.Columns.Where(it => it.IsIdentity).Count() > 0;
}
private void AddChildList(List<SubInsertTreeExpression> 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<object>))
{
childList = new List<object>() { childList };
}
if (!string.IsNullOrEmpty(subMemberName) &&subMemberName!=childName)
{
foreach (var child in childList as IEnumerable<object>)
{
child.GetType().GetProperty(subMemberName).SetValue(child, pkValue);
}
}
var type = (childList as IEnumerable<object>).First().GetType();
this.Context.InitMappingInfo(type);
var entityInfo = this.Context.EntityMaintenance.GetEntityInfo(type);
var isIdentity = IsIdEntity(entityInfo);
var tableName = entityInfo.DbTableName;
List<Dictionary<string, object>> insertList = new List<Dictionary<string, object>>();
var entityList = (childList as IEnumerable<object>).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<string, object> GetInsertDictionary(object insetObject, EntityInfo subEntity)
{
Dictionary<string, object> insertDictionary = new Dictionary<string, object>();
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; MemberExpression listMember = null;
sublist = null;
if (subMemberException.Expression is MethodCallExpression) if (subMemberException.Expression is MethodCallExpression)
{ {
listMember = (subMemberException.Expression as MethodCallExpression).Arguments.First() as MemberExpression; listMember = (subMemberException.Expression as MethodCallExpression).Arguments.First() as MemberExpression;
@ -191,32 +195,47 @@ namespace SqlSugar
} }
if (listMember == null) if (listMember == null)
{ {
listMember = (items as LambdaExpression).Body as MemberExpression; listMember = (item.Expression as LambdaExpression).Body as MemberExpression;
subMemberName = Guid.NewGuid().ToString();
} }
sublist = inserts.First().GetType().GetProperty(listMember.Member.Name).GetValue(inserts.First()); childName = listMember.Member.Name;
return childName;
} }
private void SetItems(Dictionary<string, object> 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) lambdaExpression = (item.Expression as LambdaExpression).Body;
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));
}
} }
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;
} }
} }
} }

View File

@ -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<GetSubInsertTree> ChildExpression { get; set; }
}
internal class SubInsertTreeExpression
{
public Expression Expression { get; set; }
public List<SubInsertTreeExpression> Childs { get; set; }
}
}

View File

@ -6,6 +6,7 @@ namespace SqlSugar
public interface ISubInsertable<T> public interface ISubInsertable<T>
{ {
ISubInsertable<T> AddSubList(Expression<Func<T, object>> items); ISubInsertable<T> AddSubList(Expression<Func<T, object>> items);
ISubInsertable<T> AddSubList(Expression<Func<T, GetSubInsertTree>> tree);
object ExecuteReturnPrimaryKey(); object ExecuteReturnPrimaryKey();
} }
} }

View File

@ -29,7 +29,8 @@ namespace SqlSugar
IInsertable<T> IgnoreColumns(params string[]columns); IInsertable<T> IgnoreColumns(params string[]columns);
IInsertable<T> IgnoreColumns(bool ignoreNullColumn, bool isOffIdentity = false); IInsertable<T> IgnoreColumns(bool ignoreNullColumn, bool isOffIdentity = false);
ISubInsertable<T> AddSubList(Expression<Func<T, object>> SubForeignKey); ISubInsertable<T> AddSubList(Expression<Func<T, object>> subForeignKey);
ISubInsertable<T> AddSubList(Expression<Func<T, GetSubInsertTree>> tree);
IInsertable<T> EnableDiffLogEvent(object businessData = null); IInsertable<T> EnableDiffLogEvent(object businessData = null);
IInsertable<T> RemoveDataCache(); IInsertable<T> RemoveDataCache();

View File

@ -88,6 +88,7 @@
<Compile Include="Abstract\FilterProvider\FilterProvider.cs" /> <Compile Include="Abstract\FilterProvider\FilterProvider.cs" />
<Compile Include="Abstract\InsertableProvider\InsertableProvider.cs" /> <Compile Include="Abstract\InsertableProvider\InsertableProvider.cs" />
<Compile Include="Abstract\DeleteProvider\DeleteableProvider.cs" /> <Compile Include="Abstract\DeleteProvider\DeleteableProvider.cs" />
<Compile Include="Entities\SubInsertTree.cs" />
<Compile Include="Infrastructure\KdbndpInserttable.cs" /> <Compile Include="Infrastructure\KdbndpInserttable.cs" />
<Compile Include="Interface\ISubInsertable.cs" /> <Compile Include="Interface\ISubInsertable.cs" />
<Compile Include="Abstract\InsertableProvider\SubInserable.cs" /> <Compile Include="Abstract\InsertableProvider\SubInserable.cs" />