mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	AggregateRootRepository
This commit is contained in:
		@@ -57,11 +57,11 @@ namespace FreeSql
 | 
				
			|||||||
        public Type EntityType => _repository.EntityType;
 | 
					        public Type EntityType => _repository.EntityType;
 | 
				
			||||||
        public IDataFilter<TEntity> DataFilter => _repository.DataFilter;
 | 
					        public IDataFilter<TEntity> DataFilter => _repository.DataFilter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Attach(TEntity entity) => AttachCascade(entity);
 | 
					        public void Attach(TEntity entity) => AttachAggregateRoot(entity);
 | 
				
			||||||
        public void Attach(IEnumerable<TEntity> entity)
 | 
					        public void Attach(IEnumerable<TEntity> entity)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            foreach (var item in entity)
 | 
					            foreach (var item in entity)
 | 
				
			||||||
                AttachCascade(item);
 | 
					                AttachAggregateRoot(item);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public IBaseRepository<TEntity> AttachOnlyPrimary(TEntity data) => _repository.AttachOnlyPrimary(data);
 | 
					        public IBaseRepository<TEntity> AttachOnlyPrimary(TEntity data) => _repository.AttachOnlyPrimary(data);
 | 
				
			||||||
        public Dictionary<string, object[]> CompareState(TEntity newdata) => _repository.CompareState(newdata);
 | 
					        public Dictionary<string, object[]> CompareState(TEntity newdata) => _repository.CompareState(newdata);
 | 
				
			||||||
@@ -120,7 +120,7 @@ namespace FreeSql
 | 
				
			|||||||
            if (data == null) throw new ArgumentNullException(nameof(data));
 | 
					            if (data == null) throw new ArgumentNullException(nameof(data));
 | 
				
			||||||
            var key = Orm.GetEntityKeyString(EntityType, data, false);
 | 
					            var key = Orm.GetEntityKeyString(EntityType, data, false);
 | 
				
			||||||
            var state = new EntityState((TEntity)EntityType.CreateInstanceGetDefaultValue(), key);
 | 
					            var state = new EntityState((TEntity)EntityType.CreateInstanceGetDefaultValue(), key);
 | 
				
			||||||
            AggregateRootUtils.MapEntityValueCascade(Orm, EntityType, data, state.Value);
 | 
					            AggregateRootUtils.MapEntityValue(Orm, EntityType, data, state.Value);
 | 
				
			||||||
            return state;
 | 
					            return state;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        bool? ExistsInStates(object data)
 | 
					        bool? ExistsInStates(object data)
 | 
				
			||||||
@@ -130,7 +130,7 @@ namespace FreeSql
 | 
				
			|||||||
            if (string.IsNullOrEmpty(key)) return null;
 | 
					            if (string.IsNullOrEmpty(key)) return null;
 | 
				
			||||||
            return _states.ContainsKey(key);
 | 
					            return _states.ContainsKey(key);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void AttachCascade(TEntity entity)
 | 
					        void AttachAggregateRoot(TEntity entity)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var state = CreateEntityState(entity);
 | 
					            var state = CreateEntityState(entity);
 | 
				
			||||||
            if (_states.ContainsKey(state.Key)) _states[state.Key] = state;
 | 
					            if (_states.ContainsKey(state.Key)) _states[state.Key] = state;
 | 
				
			||||||
@@ -138,17 +138,18 @@ namespace FreeSql
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Select
 | 
					        #region Selectoriginal
 | 
				
			||||||
        public virtual ISelect<TEntity> Select
 | 
					        public virtual ISelect<TEntity> Select => SelectAggregateRoot;
 | 
				
			||||||
 | 
					        ISelect<TEntity> SelectAggregateRoot
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var query = _repository.Select.TrackToList(SelectTrackingAggregateRootNavigate);
 | 
					                var query = _repository.Select.TrackToList(SelectAggregateRootTracking);
 | 
				
			||||||
                SelectFetchAggregateRootNavigate(query, EntityType, "", new Stack<Type>());
 | 
					                SelectAggregateRootNavigateReader(query, EntityType, "", new Stack<Type>());
 | 
				
			||||||
                return query;
 | 
					                return query;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void SelectFetchAggregateRootNavigate<T1>(ISelect<T1> currentQuery, Type entityType, string navigatePath, Stack<Type> ignores)
 | 
					        void SelectAggregateRootNavigateReader<T1>(ISelect<T1> currentQuery, Type entityType, string navigatePath, Stack<Type> ignores)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (ignores.Any(a => a == entityType)) return;
 | 
					            if (ignores.Any(a => a == entityType)) return;
 | 
				
			||||||
            ignores.Push(entityType);
 | 
					            ignores.Push(entityType);
 | 
				
			||||||
@@ -164,12 +165,12 @@ namespace FreeSql
 | 
				
			|||||||
                    case TableRefType.OneToOne:
 | 
					                    case TableRefType.OneToOne:
 | 
				
			||||||
                        if (ignores.Any(a => a == tbref.RefEntityType)) break;
 | 
					                        if (ignores.Any(a => a == tbref.RefEntityType)) break;
 | 
				
			||||||
                        currentQuery.IncludeByPropertyName(navigateExpression);
 | 
					                        currentQuery.IncludeByPropertyName(navigateExpression);
 | 
				
			||||||
                        SelectFetchAggregateRootNavigate(currentQuery, tbref.RefEntityType, navigateExpression, ignores);
 | 
					                        SelectAggregateRootNavigateReader(currentQuery, tbref.RefEntityType, navigateExpression, ignores);
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case TableRefType.OneToMany:
 | 
					                    case TableRefType.OneToMany:
 | 
				
			||||||
                        var ignoresCopy = new Stack<Type>(ignores.ToArray());
 | 
					                        var ignoresCopy = new Stack<Type>(ignores.ToArray());
 | 
				
			||||||
                        currentQuery.IncludeByPropertyName(navigateExpression, then =>
 | 
					                        currentQuery.IncludeByPropertyName(navigateExpression, then =>
 | 
				
			||||||
                            SelectFetchAggregateRootNavigate(then, tbref.RefEntityType, "", ignoresCopy));
 | 
					                            SelectAggregateRootNavigateReader(then, tbref.RefEntityType, "", ignoresCopy));
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
                    case TableRefType.ManyToMany:
 | 
					                    case TableRefType.ManyToMany:
 | 
				
			||||||
                        currentQuery.IncludeByPropertyName(navigateExpression);
 | 
					                        currentQuery.IncludeByPropertyName(navigateExpression);
 | 
				
			||||||
@@ -181,7 +182,7 @@ namespace FreeSql
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            ignores.Pop();
 | 
					            ignores.Pop();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void SelectTrackingAggregateRootNavigate(object list)
 | 
					        void SelectAggregateRootTracking(object list)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (list == null) return;
 | 
					            if (list == null) return;
 | 
				
			||||||
            var ls = list as IEnumerable<TEntity>;
 | 
					            var ls = list as IEnumerable<TEntity>;
 | 
				
			||||||
@@ -202,7 +203,7 @@ namespace FreeSql
 | 
				
			|||||||
                        if (Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return;
 | 
					                        if (Orm.CodeFirst.GetTableByEntity(itemType)?.Primarys.Any() != true) return;
 | 
				
			||||||
                        if (itemType.GetConstructor(Type.EmptyTypes) == null) return;
 | 
					                        if (itemType.GetConstructor(Type.EmptyTypes) == null) return;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    AttachCascade(item as TEntity);
 | 
					                    AttachAggregateRoot(item as TEntity);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,28 +15,28 @@ namespace FreeSql
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    partial class AggregateRootRepository<TEntity>
 | 
					    partial class AggregateRootRepository<TEntity>
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public TEntity Insert(TEntity entity) => InsertCascade(new[] { entity }).FirstOrDefault();
 | 
					        public TEntity Insert(TEntity entity) => InsertAggregateRoot(new[] { entity }).FirstOrDefault();
 | 
				
			||||||
        public List<TEntity> Insert(IEnumerable<TEntity> entitys) => InsertCascade(entitys);
 | 
					        public List<TEntity> Insert(IEnumerable<TEntity> entitys) => InsertAggregateRoot(entitys);
 | 
				
			||||||
        public TEntity InsertOrUpdate(TEntity entity) => InsertOrUpdateCascade(entity);
 | 
					        public TEntity InsertOrUpdate(TEntity entity) => InsertOrUpdateAggregateRoot(entity);
 | 
				
			||||||
        public int Update(TEntity entity) => UpdateCascade(new[] { entity });
 | 
					        public int Update(TEntity entity) => UpdateAggregateRoot(new[] { entity });
 | 
				
			||||||
        public int Update(IEnumerable<TEntity> entitys) => UpdateCascade(entitys);
 | 
					        public int Update(IEnumerable<TEntity> entitys) => UpdateAggregateRoot(entitys);
 | 
				
			||||||
        public int Delete(TEntity entity) => DeleteCascade(new[] { entity });
 | 
					        public int Delete(TEntity entity) => DeleteAggregateRoot(new[] { entity });
 | 
				
			||||||
        public int Delete(IEnumerable<TEntity> entitys) => DeleteCascade(entitys);
 | 
					        public int Delete(IEnumerable<TEntity> entitys) => DeleteAggregateRoot(entitys);
 | 
				
			||||||
        public int Delete(Expression<Func<TEntity, bool>> predicate) => DeleteCascade(Where(predicate).ToList());
 | 
					        public int Delete(Expression<Func<TEntity, bool>> predicate) => DeleteAggregateRoot(SelectAggregateRoot.Where(predicate).ToList());
 | 
				
			||||||
        public List<object> DeleteCascadeByDatabase(Expression<Func<TEntity, bool>> predicate)
 | 
					        public List<object> DeleteCascadeByDatabase(Expression<Func<TEntity, bool>> predicate)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var deletedOutput = new List<object>();
 | 
					            var deletedOutput = new List<object>();
 | 
				
			||||||
            DeleteCascade(Where(predicate).ToList(), deletedOutput);
 | 
					            DeleteAggregateRoot(SelectAggregateRoot.Where(predicate).ToList(), deletedOutput);
 | 
				
			||||||
            return deletedOutput;
 | 
					            return deletedOutput;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public void SaveMany(TEntity entity, string propertyName) => SaveManyCascade(entity, propertyName);
 | 
					        public void SaveMany(TEntity entity, string propertyName) => SaveManyAggregateRoot(entity, propertyName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual List<TEntity> InsertCascade(IEnumerable<TEntity> entitys)
 | 
					        protected virtual List<TEntity> InsertAggregateRoot(IEnumerable<TEntity> entitys)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var repos = new Dictionary<Type, object>();
 | 
					            var repos = new Dictionary<Type, object>();
 | 
				
			||||||
            try
 | 
					            try
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return InsertCascadeStatic(_repository, GetChildRepository, entitys);
 | 
					                return InsertAggregateRootStatic(_repository, GetChildRepository, entitys);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@@ -44,12 +44,12 @@ namespace FreeSql
 | 
				
			|||||||
                _repository.FlushState();
 | 
					                _repository.FlushState();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        protected static List<TEntity> InsertCascadeStatic(IBaseRepository<TEntity> rootRepository, Func<Type, IBaseRepository<object>> getChildRepository, IEnumerable<TEntity> rootEntitys) {
 | 
					        protected static List<TEntity> InsertAggregateRootStatic(IBaseRepository<TEntity> rootRepository, Func<Type, IBaseRepository<object>> getChildRepository, IEnumerable<TEntity> rootEntitys) {
 | 
				
			||||||
            Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
					            Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
				
			||||||
            Dictionary<Type, IBaseRepository<object>> repos = new Dictionary<Type, IBaseRepository<object>>();
 | 
					            Dictionary<Type, IBaseRepository<object>> repos = new Dictionary<Type, IBaseRepository<object>>();
 | 
				
			||||||
            return LocalInsertCascade(rootRepository, rootEntitys);
 | 
					            return LocalInsertAggregateRoot(rootRepository, rootEntitys);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool LocalCanCascade(Type entityType, object entity, bool isadd)
 | 
					            bool LocalCanAggregateRoot(Type entityType, object entity, bool isadd)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var stateKey = rootRepository.Orm.GetEntityKeyString(entityType, entity, false);
 | 
					                var stateKey = rootRepository.Orm.GetEntityKeyString(entityType, entity, false);
 | 
				
			||||||
                if (stateKey == null) return true;
 | 
					                if (stateKey == null) return true;
 | 
				
			||||||
@@ -69,10 +69,10 @@ namespace FreeSql
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            List<T1> LocalInsertCascade<T1>(IBaseRepository<T1> repository, IEnumerable<T1> entitys) where T1 : class
 | 
					            List<T1> LocalInsertAggregateRoot<T1>(IBaseRepository<T1> repository, IEnumerable<T1> entitys) where T1 : class
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var ret = repository.Insert(entitys);
 | 
					                var ret = repository.Insert(entitys);
 | 
				
			||||||
                foreach (var entity in entitys) LocalCanCascade(repository.EntityType, entity, true);
 | 
					                foreach (var entity in entitys) LocalCanAggregateRoot(repository.EntityType, entity, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var table = repository.Orm.CodeFirst.GetTableByEntity(repository.EntityType);
 | 
					                var table = repository.Orm.CodeFirst.GetTableByEntity(repository.EntityType);
 | 
				
			||||||
                foreach (var prop in table.Properties.Values)
 | 
					                foreach (var prop in table.Properties.Values)
 | 
				
			||||||
@@ -85,14 +85,14 @@ namespace FreeSql
 | 
				
			|||||||
                            var otoList = ret.Select(entity =>
 | 
					                            var otoList = ret.Select(entity =>
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                var otoItem = table.GetPropertyValue(entity, prop.Name);
 | 
					                                var otoItem = table.GetPropertyValue(entity, prop.Name);
 | 
				
			||||||
                                if (LocalCanCascade(tbref.RefEntityType, otoItem, false) == false) return null;
 | 
					                                if (LocalCanAggregateRoot(tbref.RefEntityType, otoItem, false) == false) return null;
 | 
				
			||||||
                                AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otoItem);
 | 
					                                AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otoItem);
 | 
				
			||||||
                                return otoItem;
 | 
					                                return otoItem;
 | 
				
			||||||
                            }).Where(entity => entity != null).ToArray();
 | 
					                            }).Where(entity => entity != null).ToArray();
 | 
				
			||||||
                            if (otoList.Any())
 | 
					                            if (otoList.Any())
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                var repo = getChildRepository(tbref.RefEntityType);
 | 
					                                var repo = getChildRepository(tbref.RefEntityType);
 | 
				
			||||||
                                LocalInsertCascade(repo, otoList);
 | 
					                                LocalInsertAggregateRoot(repo, otoList);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case TableRefType.OneToMany:
 | 
					                        case TableRefType.OneToMany:
 | 
				
			||||||
@@ -103,7 +103,7 @@ namespace FreeSql
 | 
				
			|||||||
                                var otmItems = new List<object>();
 | 
					                                var otmItems = new List<object>();
 | 
				
			||||||
                                foreach (var otmItem in otmEach)
 | 
					                                foreach (var otmItem in otmEach)
 | 
				
			||||||
                                {
 | 
					                                {
 | 
				
			||||||
                                    if (LocalCanCascade(tbref.RefEntityType, otmItem, false) == false) continue;
 | 
					                                    if (LocalCanAggregateRoot(tbref.RefEntityType, otmItem, false) == false) continue;
 | 
				
			||||||
                                    otmItems.Add(otmItem);
 | 
					                                    otmItems.Add(otmItem);
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otmItems);
 | 
					                                AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otmItems);
 | 
				
			||||||
@@ -112,7 +112,7 @@ namespace FreeSql
 | 
				
			|||||||
                            if (otmList.Any())
 | 
					                            if (otmList.Any())
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                var repo = getChildRepository(tbref.RefEntityType);
 | 
					                                var repo = getChildRepository(tbref.RefEntityType);
 | 
				
			||||||
                                LocalInsertCascade(repo, otmList);
 | 
					                                LocalInsertAggregateRoot(repo, otmList);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case TableRefType.ManyToMany:
 | 
					                        case TableRefType.ManyToMany:
 | 
				
			||||||
@@ -125,7 +125,7 @@ namespace FreeSql
 | 
				
			|||||||
                            if (mtmMidList.Any())
 | 
					                            if (mtmMidList.Any())
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                var repo = getChildRepository(tbref.RefMiddleEntityType);
 | 
					                                var repo = getChildRepository(tbref.RefMiddleEntityType);
 | 
				
			||||||
                                LocalInsertCascade(repo, mtmMidList);
 | 
					                                LocalInsertAggregateRoot(repo, mtmMidList);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            break;
 | 
					                            break;
 | 
				
			||||||
                        case TableRefType.PgArrayToMany:
 | 
					                        case TableRefType.PgArrayToMany:
 | 
				
			||||||
@@ -136,7 +136,7 @@ namespace FreeSql
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        protected virtual TEntity InsertOrUpdateCascade(TEntity entity)
 | 
					        protected virtual TEntity InsertOrUpdateAggregateRoot(TEntity entity)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
					            var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
				
			||||||
            if (entity == null) throw new ArgumentNullException(nameof(entity));
 | 
					            if (entity == null) throw new ArgumentNullException(nameof(entity));
 | 
				
			||||||
@@ -150,13 +150,13 @@ namespace FreeSql
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            if (flagExists == true)
 | 
					            if (flagExists == true)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var affrows = UpdateCascade(new[] { entity });
 | 
					                var affrows = UpdateAggregateRoot(new[] { entity });
 | 
				
			||||||
                if (affrows > 0) return entity;
 | 
					                if (affrows > 0) return entity;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Orm.ClearEntityPrimaryValueWithIdentity(EntityType, entity);
 | 
					            Orm.ClearEntityPrimaryValueWithIdentity(EntityType, entity);
 | 
				
			||||||
            return InsertCascade(new[] { entity }).FirstOrDefault();
 | 
					            return InsertAggregateRoot(new[] { entity }).FirstOrDefault();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        protected virtual int UpdateCascade(IEnumerable<TEntity> entitys)
 | 
					        protected virtual int UpdateAggregateRoot(IEnumerable<TEntity> entitys)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
					            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
				
			||||||
            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
					            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
				
			||||||
@@ -165,12 +165,12 @@ namespace FreeSql
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
					                var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
				
			||||||
                if (_states.TryGetValue(stateKey, out var state) == false) throw new Exception($"AggregateRootRepository 使用仓储对象查询后,才可以更新数据 {Orm.GetEntityString(EntityType, entity)}");
 | 
					                if (_states.TryGetValue(stateKey, out var state) == false) throw new Exception($"AggregateRootRepository 使用仓储对象查询后,才可以更新数据 {Orm.GetEntityString(EntityType, entity)}");
 | 
				
			||||||
                AggregateRootUtils.CompareEntityValueCascade(Orm, EntityType, state.Value, entity, null, insertLog, updateLog, deleteLog);
 | 
					                AggregateRootUtils.CompareEntityValue(Orm, EntityType, state.Value, entity, null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
                AttachCascade(entity);
 | 
					                AttachAggregateRoot(entity);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return insertLog.Count + updateLog.Count + deleteLog.Count;
 | 
					            return insertLog.Count + updateLog.Count + deleteLog.Count;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        protected virtual int DeleteCascade(IEnumerable<TEntity> entitys, List<object> deletedOutput = null)
 | 
					        protected virtual int DeleteAggregateRoot(IEnumerable<TEntity> entitys, List<object> deletedOutput = null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
					            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
				
			||||||
            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
					            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
				
			||||||
@@ -178,22 +178,22 @@ namespace FreeSql
 | 
				
			|||||||
            foreach (var entity in entitys)
 | 
					            foreach (var entity in entitys)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
					                var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
				
			||||||
                AggregateRootUtils.CompareEntityValueCascade(Orm, EntityType, entity, null, null, insertLog, updateLog, deleteLog);
 | 
					                AggregateRootUtils.CompareEntityValue(Orm, EntityType, entity, null, null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
                _states.Remove(stateKey);
 | 
					                _states.Remove(stateKey);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (deletedOutput != null) deletedOutput.AddRange(deleteLog.Select(a => a.Item2));
 | 
					            if (deletedOutput != null) deletedOutput.AddRange(deleteLog.Select(a => a.Item2));
 | 
				
			||||||
            return deleteLog.Count;
 | 
					            return deleteLog.Count;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected virtual void SaveManyCascade(TEntity entity, string propertyName)
 | 
					        protected virtual void SaveManyAggregateRoot(TEntity entity, string propertyName)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
					            List<NativeTuple<Type, object>> insertLog = new List<NativeTuple<Type, object>>();
 | 
				
			||||||
            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
					            List<NativeTuple<Type, object, object, List<string>>> updateLog = new List<NativeTuple<Type, object, object, List<string>>>();
 | 
				
			||||||
            List<NativeTuple<Type, object>> deleteLog = new List<NativeTuple<Type, object>>();
 | 
					            List<NativeTuple<Type, object>> deleteLog = new List<NativeTuple<Type, object>>();
 | 
				
			||||||
            var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
					            var stateKey = Orm.GetEntityKeyString(EntityType, entity, false);
 | 
				
			||||||
            if (_states.TryGetValue(stateKey, out var state) == false) throw new Exception($"AggregateRootRepository 使用仓储对象查询后,才可以保存数据 {Orm.GetEntityString(EntityType, entity)}");
 | 
					            if (_states.TryGetValue(stateKey, out var state) == false) throw new Exception($"AggregateRootRepository 使用仓储对象查询后,才可以保存数据 {Orm.GetEntityString(EntityType, entity)}");
 | 
				
			||||||
            AggregateRootUtils.CompareEntityValueCascade(Orm, EntityType, state.Value, entity, propertyName, insertLog, updateLog, deleteLog);
 | 
					            AggregateRootUtils.CompareEntityValue(Orm, EntityType, state.Value, entity, propertyName, insertLog, updateLog, deleteLog);
 | 
				
			||||||
            AttachCascade(entity);
 | 
					            AttachAggregateRoot(entity);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        protected List<TEntity> _dataEditing;
 | 
					        protected List<TEntity> _dataEditing;
 | 
				
			||||||
@@ -212,7 +212,7 @@ namespace FreeSql
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                _statesEditing.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) =>
 | 
					                _statesEditing.AddOrUpdate(key, k => CreateEntityState(item), (k, ov) =>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    AggregateRootUtils.MapEntityValueCascade(Orm, EntityType, item, ov.Value);
 | 
					                    AggregateRootUtils.MapEntityValue(Orm, EntityType, item, ov.Value);
 | 
				
			||||||
                    ov.Time = DateTime.Now;
 | 
					                    ov.Time = DateTime.Now;
 | 
				
			||||||
                    return ov;
 | 
					                    return ov;
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@@ -238,11 +238,11 @@ namespace FreeSql
 | 
				
			|||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    _states[key] = state;
 | 
					                    _states[key] = state;
 | 
				
			||||||
                    AggregateRootUtils.CompareEntityValueCascade(Orm, EntityType, state.Value, item, null, insertLog, updateLog, deleteLog);
 | 
					                    AggregateRootUtils.CompareEntityValue(Orm, EntityType, state.Value, item, null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                foreach (var item in _statesEditing.Values.OrderBy(a => a.Time))
 | 
					                foreach (var item in _statesEditing.Values.OrderBy(a => a.Time))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    AggregateRootUtils.CompareEntityValueCascade(Orm, EntityType, item, null, null, insertLog, updateLog, deleteLog);
 | 
					                    AggregateRootUtils.CompareEntityValue(Orm, EntityType, item, null, null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            finally
 | 
					            finally
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ using System.Reflection;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static class AggregateRootUtils
 | 
					static class AggregateRootUtils
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public static void CompareEntityValueCascade(IFreeSql fsql, Type entityType, object entityBefore, object entityAfter, string navigatePropertyName,
 | 
					    public static void CompareEntityValue(IFreeSql fsql, Type entityType, object entityBefore, object entityAfter, string navigatePropertyName,
 | 
				
			||||||
        List<NativeTuple<Type, object>> insertLog,
 | 
					        List<NativeTuple<Type, object>> insertLog,
 | 
				
			||||||
        List<NativeTuple<Type, object, object, List<string>>> updateLog,
 | 
					        List<NativeTuple<Type, object, object, List<string>>> updateLog,
 | 
				
			||||||
        List<NativeTuple<Type, object>> deleteLog)
 | 
					        List<NativeTuple<Type, object>> deleteLog)
 | 
				
			||||||
@@ -28,7 +28,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
        if (entityBefore != null && entityAfter == null)
 | 
					        if (entityBefore != null && entityAfter == null)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            deleteLog.Add(NativeTuple.Create(entityType, entityBefore));
 | 
					            deleteLog.Add(NativeTuple.Create(entityType, entityBefore));
 | 
				
			||||||
            EachNavigateCascade(fsql, entityType, entityBefore, (path, tr, ct, stackvs) =>
 | 
					            NavigateReader(fsql, entityType, entityBefore, (path, tr, ct, stackvs) =>
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
					                deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
@@ -60,7 +60,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
            switch (tbref.RefType)
 | 
					            switch (tbref.RefType)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                case TableRefType.OneToOne:
 | 
					                case TableRefType.OneToOne:
 | 
				
			||||||
                    CompareEntityValueCascade(fsql, tbref.RefEntityType, propvalBefore, propvalAfter, null, insertLog, updateLog, deleteLog);
 | 
					                    CompareEntityValue(fsql, tbref.RefEntityType, propvalBefore, propvalAfter, null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case TableRefType.OneToMany:
 | 
					                case TableRefType.OneToMany:
 | 
				
			||||||
                    LocalCompareEntityValueCollection(tbref, propvalBefore as IEnumerable, propvalAfter as IEnumerable);
 | 
					                    LocalCompareEntityValueCollection(tbref, propvalBefore as IEnumerable, propvalAfter as IEnumerable);
 | 
				
			||||||
@@ -91,7 +91,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
                foreach (var item in collectionBefore as IEnumerable)
 | 
					                foreach (var item in collectionBefore as IEnumerable)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    deleteLog.Add(NativeTuple.Create(elementType, item));
 | 
					                    deleteLog.Add(NativeTuple.Create(elementType, item));
 | 
				
			||||||
                    EachNavigateCascade(fsql, elementType, item, (path, tr, ct, stackvs) =>
 | 
					                    NavigateReader(fsql, elementType, item, (path, tr, ct, stackvs) =>
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
					                        deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
@@ -117,7 +117,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    var value = dictBefore[key];
 | 
					                    var value = dictBefore[key];
 | 
				
			||||||
                    deleteLog.Add(NativeTuple.Create(elementType, value));
 | 
					                    deleteLog.Add(NativeTuple.Create(elementType, value));
 | 
				
			||||||
                    EachNavigateCascade(fsql, elementType, value, (path, tr, ct, stackvs) =>
 | 
					                    NavigateReader(fsql, elementType, value, (path, tr, ct, stackvs) =>
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
					                        deleteLog.Add(NativeTuple.Create(ct, stackvs.First()));
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
@@ -133,20 +133,21 @@ static class AggregateRootUtils
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            foreach (var key in dictBefore.Keys)
 | 
					            foreach (var key in dictBefore.Keys)
 | 
				
			||||||
                CompareEntityValueCascade(fsql, elementType, dictBefore[key], dictAfter[key], null, insertLog, updateLog, deleteLog);
 | 
					                CompareEntityValue(fsql, elementType, dictBefore[key], dictAfter[key], null, insertLog, updateLog, deleteLog);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    public static void EachNavigateCascade(IFreeSql fsql, Type rootType, object rootEntity, Action<string, TableRef, Type, List<object>> callback)
 | 
					
 | 
				
			||||||
 | 
					    public static void NavigateReader(IFreeSql fsql, Type rootType, object rootEntity, Action<string, TableRef, Type, List<object>> callback)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
					        Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
				
			||||||
        var statckPath = new Stack<string>();
 | 
					        var statckPath = new Stack<string>();
 | 
				
			||||||
        var stackValues = new List<object>();
 | 
					        var stackValues = new List<object>();
 | 
				
			||||||
        statckPath.Push("_");
 | 
					        statckPath.Push("_");
 | 
				
			||||||
        stackValues.Add(rootEntity);
 | 
					        stackValues.Add(rootEntity);
 | 
				
			||||||
        LocalEachNavigate(rootType, rootEntity);
 | 
					        LocalNavigateReader(rootType, rootEntity);
 | 
				
			||||||
        ignores.Clear();
 | 
					        ignores.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void LocalEachNavigate(Type entityType, object entity)
 | 
					        void LocalNavigateReader(Type entityType, object entity)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (entity == null) return;
 | 
					            if (entity == null) return;
 | 
				
			||||||
            if (entityType == null) entityType = entity.GetType();
 | 
					            if (entityType == null) entityType = entity.GetType();
 | 
				
			||||||
@@ -170,7 +171,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
                        statckPath.Push(prop.Name);
 | 
					                        statckPath.Push(prop.Name);
 | 
				
			||||||
                        stackValues.Add(propval);
 | 
					                        stackValues.Add(propval);
 | 
				
			||||||
                        callback?.Invoke(string.Join(".", statckPath), tbref, tbref.RefEntityType, stackValues);
 | 
					                        callback?.Invoke(string.Join(".", statckPath), tbref, tbref.RefEntityType, stackValues);
 | 
				
			||||||
                        LocalEachNavigate(tbref.RefEntityType, propval);
 | 
					                        LocalNavigateReader(tbref.RefEntityType, propval);
 | 
				
			||||||
                        stackValues.RemoveAt(stackValues.Count - 1);
 | 
					                        stackValues.RemoveAt(stackValues.Count - 1);
 | 
				
			||||||
                        statckPath.Pop();
 | 
					                        statckPath.Pop();
 | 
				
			||||||
                        break;
 | 
					                        break;
 | 
				
			||||||
@@ -180,7 +181,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
                            statckPath.Push($"{prop.Name[idx++]}");
 | 
					                            statckPath.Push($"{prop.Name[idx++]}");
 | 
				
			||||||
                            stackValues.Add(val);
 | 
					                            stackValues.Add(val);
 | 
				
			||||||
                            callback?.Invoke(string.Join(".", statckPath), tbref, tbref.RefEntityType, stackValues);
 | 
					                            callback?.Invoke(string.Join(".", statckPath), tbref, tbref.RefEntityType, stackValues);
 | 
				
			||||||
                            LocalEachNavigate(tbref.RefEntityType, val);
 | 
					                            LocalNavigateReader(tbref.RefEntityType, val);
 | 
				
			||||||
                            stackValues.RemoveAt(stackValues.Count - 1);
 | 
					                            stackValues.RemoveAt(stackValues.Count - 1);
 | 
				
			||||||
                            statckPath.Pop();
 | 
					                            statckPath.Pop();
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
@@ -204,8 +205,7 @@ static class AggregateRootUtils
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static ConcurrentDictionary<Type, Action<IFreeSql, object, object>> _dicMapEntityValueCascade = new ConcurrentDictionary<Type, Action<IFreeSql, object, object>>();
 | 
					    public static void MapEntityValue(IFreeSql fsql, Type rootEntityType, object rootEntityFrom, object rootEntityTo)
 | 
				
			||||||
    public static void MapEntityValueCascade(this IFreeSql fsql, Type rootEntityType, object rootEntityFrom, object rootEntityTo)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
					        Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
 | 
				
			||||||
        LocalMapEntityValue(rootEntityType, rootEntityFrom, rootEntityTo);
 | 
					        LocalMapEntityValue(rootEntityType, rootEntityFrom, rootEntityTo);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user