123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Text;
- using System.Threading.Tasks;
- namespace SqlSugar
- {
- public partial class UpdateNavProvider<Root, T> where T : class, new() where Root : class, new()
- {
- public NavigateType? _NavigateType { get; set; }
- private void UpdateOneToMany<TChild>(string name, EntityColumnInfo nav) where TChild : class, new()
- {
- if (_Options?.OneToManyInsertOrUpdate == true)
- {
- InsertOrUpdate<TChild>(name,nav);
- }
- else
- {
- DeleteInsert<TChild>(name, nav);
- }
- }
- private void InsertOrUpdate<TChild>(string name, EntityColumnInfo nav) where TChild : class, new()
- {
- List<TChild> children = new List<TChild>();
- var parentEntity = _ParentEntity;
- var parentList = _ParentList;
- var parentNavigateProperty = parentEntity.Columns.FirstOrDefault(it => it.PropertyName == name);
- var thisEntity = this._Context.EntityMaintenance.GetEntityInfo<TChild>();
- var thisPkColumn = GetPkColumnByNav2(thisEntity, nav);
- var thisFkColumn = GetFKColumnByNav(thisEntity, nav);
- EntityColumnInfo parentPkColumn = GetParentPkColumn();
- EntityColumnInfo parentNavColumn = GetParentPkNavColumn(nav);
- if (parentNavColumn != null)
- {
- parentPkColumn = parentNavColumn;
- }
- if (ParentIsPk(parentNavigateProperty))
- {
- parentPkColumn = this._ParentEntity.Columns.FirstOrDefault(it => it.IsPrimarykey);
- }
- var ids = new List<object>();
- foreach (var item in parentList)
- {
- var parentValue = parentPkColumn.PropertyInfo.GetValue(item);
- var childs = parentNavigateProperty.PropertyInfo.GetValue(item) as List<TChild>;
- if (childs != null)
- {
- foreach (var child in childs)
- {
- thisFkColumn.PropertyInfo.SetValue(child, parentValue, null);
- }
- children.AddRange(childs);
- }
- ids.Add(parentValue);
- if (_Options?.OneToManyNoDeleteNull == true && childs == null)
- {
- ids.Remove(parentValue);
- }
- }
- if (NotAny(name))
- {
- DeleteMany(thisEntity, ids, thisFkColumn.DbColumnName);
- if (this._Options?.OneToManyEnableLogicDelete == true)
- {
- var locgicColumn = thisEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase("IsDeleted") || it.PropertyName.EqualCase("IsDelete"));
- Check.ExceptionEasy(
- locgicColumn == null,
- thisEntity.EntityName + "Logical deletion requires the entity to have the IsDeleted property",
- thisEntity.EntityName + "假删除需要实体有IsDeleted属性");
- List<IConditionalModel> conditionalModels = new List<IConditionalModel>();
- conditionalModels.Add(new ConditionalModel()
- {
- FieldName = thisFkColumn.DbColumnName,
- FieldValue = string.Join(",", ids.Distinct()),
- ConditionalType = ConditionalType.In,
- CSharpTypeName = thisFkColumn?.PropertyInfo?.PropertyType?.Name
- });
- var sqlObj = _Context.Queryable<object>().SqlBuilder.ConditionalModelToSql(conditionalModels);
- this._Context.Updateable<object>()
- .AS(thisEntity.DbTableName)
- .Where(sqlObj.Key, sqlObj.Value)
- .SetColumns(locgicColumn.DbColumnName, true)
- .ExecuteCommand();
- }
- else
- {
- var list=this._Context.Queryable<TChild>()
- .AS(thisEntity.DbTableName)
- .In(thisFkColumn.DbColumnName, ids.Distinct().ToList())
- .ToList();
- List<TChild> result = GetNoExistsId(list, children, thisPkColumn.PropertyName);
- if (result.Any())
- {
- this._Context.Deleteable(result).ExecuteCommand();
- }
- }
- _NavigateType = NavigateType.OneToMany;
- InsertDatas(children, thisPkColumn);
- }
- else
- {
- this._ParentList = children.Cast<object>().ToList();
- }
- _NavigateType = null;
- SetNewParent<TChild>(thisEntity, thisPkColumn);
- }
- private void DeleteInsert<TChild>(string name, EntityColumnInfo nav) where TChild : class, new()
- {
- List<TChild> children = new List<TChild>();
- var parentEntity = _ParentEntity;
- var parentList = _ParentList;
- var parentNavigateProperty = parentEntity.Columns.FirstOrDefault(it => it.PropertyName == name);
- var thisEntity = this._Context.EntityMaintenance.GetEntityInfo<TChild>();
- var thisPkColumn = GetPkColumnByNav2(thisEntity, nav);
- var thisFkColumn = GetFKColumnByNav(thisEntity, nav);
- EntityColumnInfo parentPkColumn = GetParentPkColumn();
- EntityColumnInfo parentNavColumn = GetParentPkNavColumn(nav);
- if (parentNavColumn != null)
- {
- parentPkColumn = parentNavColumn;
- }
- if (ParentIsPk(parentNavigateProperty))
- {
- parentPkColumn = this._ParentEntity.Columns.FirstOrDefault(it => it.IsPrimarykey);
- }
- var ids = new List<object>();
- foreach (var item in parentList)
- {
- var parentValue = parentPkColumn.PropertyInfo.GetValue(item);
- var childs = parentNavigateProperty.PropertyInfo.GetValue(item) as List<TChild>;
- if (childs != null)
- {
- foreach (var child in childs)
- {
- thisFkColumn.PropertyInfo.SetValue(child, parentValue, null);
- }
- children.AddRange(childs);
- }
- ids.Add(parentValue);
- if (_Options?.OneToManyNoDeleteNull == true && childs == null)
- {
- ids.Remove(parentValue);
- }
- }
- if (NotAny(name))
- {
- DeleteMany(thisEntity, ids, thisFkColumn.DbColumnName);
- if (this._Options?.OneToManyEnableLogicDelete == true)
- {
- var locgicColumn = thisEntity.Columns.FirstOrDefault(it => it.PropertyName.EqualCase("IsDeleted") || it.PropertyName.EqualCase("IsDelete"));
- Check.ExceptionEasy(
- locgicColumn == null,
- thisEntity.EntityName + "Logical deletion requires the entity to have the IsDeleted property",
- thisEntity.EntityName + "假删除需要实体有IsDeleted属性");
- List<IConditionalModel> conditionalModels = new List<IConditionalModel>();
- conditionalModels.Add(new ConditionalModel()
- {
- FieldName = thisFkColumn.DbColumnName,
- FieldValue = string.Join(",", ids.Distinct()),
- ConditionalType = ConditionalType.In,
- CSharpTypeName = thisFkColumn?.PropertyInfo?.PropertyType?.Name
- });
- var sqlObj = _Context.Queryable<object>().SqlBuilder.ConditionalModelToSql(conditionalModels);
- this._Context.Updateable<object>()
- .AS(thisEntity.DbTableName)
- .Where(sqlObj.Key, sqlObj.Value)
- .SetColumns(locgicColumn.DbColumnName, true)
- .ExecuteCommand();
- }
- else
- {
- if (this._Context?.CurrentConnectionConfig?.MoreSettings?.IsAutoDeleteQueryFilter == true)
- {
- this._Context.Deleteable<object>()
- .AS(thisEntity.DbTableName)
- .EnableQueryFilter(thisEntity.Type)
- .In(thisFkColumn.DbColumnName, ids.Distinct().ToList()).ExecuteCommand();
- }
- else
- {
- this._Context.Deleteable<object>()
- .AS(thisEntity.DbTableName)
- .In(thisFkColumn.DbColumnName, ids.Distinct().ToList()).ExecuteCommand();
- }
- }
- _NavigateType = NavigateType.OneToMany;
- InsertDatas(children, thisPkColumn);
- }
- else
- {
- this._ParentList = children.Cast<object>().ToList();
- }
- _NavigateType = null;
- SetNewParent<TChild>(thisEntity, thisPkColumn);
- }
- private static bool ParentIsPk(EntityColumnInfo parentNavigateProperty)
- {
- return parentNavigateProperty != null &&
- parentNavigateProperty.Navigat != null &&
- parentNavigateProperty.Navigat.NavigatType == NavigateType.OneToMany &&
- parentNavigateProperty.Navigat.Name2 == null;
- }
- private void DeleteMany(EntityInfo thisEntity, List<object> ids,string fkName)
- {
- if (_Options == null||_Options.OneToManyDeleteAll==false)
- {
- return;
- }
- var oneToManys = thisEntity.Columns.Where(it => it.Navigat != null && it.Navigat.NavigatType == NavigateType.OneToMany).ToList();
- foreach (var oneToMany in oneToManys)
- {
- var fkFieldName = oneToMany.Navigat.Name2 ?? thisEntity.Columns.FirstOrDefault(it => it.IsPrimarykey).PropertyName;
- var fkDbColumnName = thisEntity.Columns.FirstOrDefault(it => it.PropertyName == fkFieldName).DbColumnName;
- var fks = this._Context.Queryable<object>()
- .AS(thisEntity.DbTableName)
- .In(fkName, ids.Distinct().ToList()).Select(fkDbColumnName).ToDataTable().Rows.Cast<System.Data.DataRow>().Select(x => x[0]).ToArray();
- var type = oneToMany.PropertyInfo.PropertyType.GenericTypeArguments[0];
- var entity = this._Context.EntityMaintenance.GetEntityInfo(type);
- var id = oneToMany.Navigat.Name;
- var column = entity.Columns.FirstOrDefault(it => it.PropertyName == id).DbColumnName;
- DeleteChild(fks, entity, column);
- this._Context.Deleteable<object>()
- .AS(entity.DbTableName)
- .In(column, fks.Distinct().ToList()).ExecuteCommand();
- }
- }
- private void DeleteChild(object[] fks, EntityInfo entity, string column)
- {
- var childs = entity.Columns.Where(it => it.Navigat != null && it.Navigat?.NavigatType == NavigateType.OneToMany).ToList();
- if (childs.Any())
- {
- var pkColumn = entity.Columns.First(it => it.IsPrimarykey);
- var pkIds = this._Context.Queryable<object>()
- .AS(entity.DbTableName)
- .In(column, fks.Distinct().ToList())
- .Select(pkColumn.DbColumnName).ToDataTable().Rows
- .Cast<System.Data.DataRow>().Select(it => it[0]).ToList();
- DeleteChildChild(pkIds, childs);
- }
- }
- int childIndex = 0;
- private void DeleteChildChild(List<object> ids, List<EntityColumnInfo> childs)
- {
- childIndex++;
- if (childIndex > 4)
- {
- Check.ExceptionEasy("Removing too many levels", "安全机制限制删除脏数据层级不能超过7层");
- }
- foreach (var columnInfo in childs)
- {
- var navigat = columnInfo.Navigat;
- var type = columnInfo.PropertyInfo.PropertyType.GenericTypeArguments[0];
- var thisEntity = this._Context.EntityMaintenance.GetEntityInfo(type);
- var fkColumn = thisEntity.Columns.FirstOrDefault(it => navigat.Name.EqualCase(it.PropertyName));
- var thisPkColumn = thisEntity.Columns.FirstOrDefault(it => it.IsPrimarykey);
- var childs2 = thisEntity.Columns.Where(it => it.Navigat != null && it.Navigat?.NavigatType == NavigateType.OneToMany).ToList(); ;
- if (childs2.Any())
- {
- var pkIds = _Context.Queryable<object>().AS(thisEntity.DbTableName)
- .In(fkColumn.DbColumnName, ids)
- .Select(thisPkColumn.DbColumnName).ToDataTable().Rows
- .Cast<System.Data.DataRow>().Select(it => it[0]).ToList();
- DeleteChildChild(pkIds, childs2);
- }
- _Context.Deleteable<object>().AS(thisEntity.DbTableName).In(fkColumn.DbColumnName, ids).ExecuteCommand();
- }
- }
- private EntityColumnInfo GetParentPkColumn()
- {
- EntityColumnInfo parentPkColumn = _ParentPkColumn;
- if (_ParentPkColumn == null)
- {
- parentPkColumn = _ParentPkColumn = this._ParentEntity.Columns.FirstOrDefault(it => it.IsPrimarykey);
- }
- return parentPkColumn;
- }
- private EntityColumnInfo GetParentPkNavColumn(EntityColumnInfo nav)
- {
- EntityColumnInfo result = null;
- if (nav.Navigat.Name2.HasValue())
- {
- result = _ParentPkColumn = this._ParentEntity.Columns.FirstOrDefault(it => it.PropertyName == nav.Navigat.Name2);
- }
- return result;
- }
- private void SetNewParent<TChild>(EntityInfo entityInfo, EntityColumnInfo entityColumnInfo) where TChild : class, new()
- {
- this._ParentEntity = entityInfo;
- this._ParentPkColumn = entityColumnInfo;
- }
- public List<TChild> GetNoExistsId<TChild>(List<TChild> old, List<TChild> newList, string pkName)
- {
- List<TChild> result = new List<TChild>();
- // 将newList中的主键属性转换为字符串集合
- var newIds = newList.Select(item => GetPropertyValueAsString(item, pkName)).ToList();
- // 获取在old中但不在newList中的主键属性值
- result = old.Where(item => !newIds.Contains(GetPropertyValueAsString(item, pkName)))
- .ToList();
- return result;
- }
- // 获取对象的属性值
- private string GetPropertyValueAsString<TChild>(TChild item, string propertyName)
- {
- var property = item.GetType().GetProperty(propertyName);
- if (property != null)
- {
- return property.GetValue(item, null)+"";
- }
- else
- {
- throw new ArgumentException($"Property '{propertyName}' not found on type {item.GetType().Name}");
- }
- }
- }
- }
|