From 8162e21ce56f2d1b0068a6603429d9fccfea5133 Mon Sep 17 00:00:00 2001 From: 2881099 <2881099@qq.com> Date: Fri, 2 Sep 2022 17:08:36 +0800 Subject: [PATCH] AggregateRootRepository --- .../AggregateRootRepositorySync.cs | 4 +- FreeSql.Repository/AggregateRootUtils.cs | 135 ++++++++++-------- .../AggregateRootRepositoryTest.cs | 3 + 3 files changed, 85 insertions(+), 57 deletions(-) diff --git a/FreeSql.Repository/AggregateRootRepositorySync.cs b/FreeSql.Repository/AggregateRootRepositorySync.cs index e3d8dc6b..6b261031 100644 --- a/FreeSql.Repository/AggregateRootRepositorySync.cs +++ b/FreeSql.Repository/AggregateRootRepositorySync.cs @@ -36,7 +36,9 @@ namespace FreeSql var repos = new Dictionary(); try { - return InsertAggregateRootStatic(_repository, GetChildRepository, entitys); + var ret = InsertAggregateRootStatic(_repository, GetChildRepository, entitys); + Attach(ret); + return ret; } finally { diff --git a/FreeSql.Repository/AggregateRootUtils.cs b/FreeSql.Repository/AggregateRootUtils.cs index 890fc7e3..74aa9b94 100644 --- a/FreeSql.Repository/AggregateRootUtils.cs +++ b/FreeSql.Repository/AggregateRootUtils.cs @@ -12,70 +12,93 @@ using System.Reflection; static class AggregateRootUtils { - public static void CompareEntityValue(IFreeSql fsql, Type entityType, object entityBefore, object entityAfter, string navigatePropertyName, + public static void CompareEntityValue(IFreeSql fsql, Type rootEntityType, object rootEntityBefore, object rootEntityAfter, string rootNavigatePropertyName, List> insertLog, List>> updateLog, List> deleteLog) { - if (entityType == null) entityType = entityBefore?.GetType() ?? entityAfter?.GetType(); - var table = fsql.CodeFirst.GetTableByEntity(entityType); - if (entityBefore == null && entityAfter == null) return; - if (entityBefore == null && entityAfter != null) + Dictionary> ignores = new Dictionary>(); + LocalCompareEntityValue(rootEntityType, rootEntityBefore, rootEntityAfter, rootNavigatePropertyName); + ignores.Clear(); + + void LocalCompareEntityValue(Type entityType, object entityBefore, object entityAfter, string navigatePropertyName) { - insertLog.Add(NativeTuple.Create(entityType, entityAfter)); - return; - } - if (entityBefore != null && entityAfter == null) - { - deleteLog.Add(NativeTuple.Create(entityType, entityBefore)); - NavigateReader(fsql, entityType, entityBefore, (path, tr, ct, stackvs) => + if (entityType == null) entityType = entityBefore?.GetType() ?? entityAfter?.GetType(); + + if (entityBefore != null) { - deleteLog.Add(NativeTuple.Create(ct, stackvs.First())); - }); - return; - } - var changes = new List(); - foreach (var col in table.ColumnsByCs.Values) - { - if (table.ColumnsByCsIgnore.ContainsKey(col.CsName)) continue; - if (table.ColumnsByCs.ContainsKey(col.CsName)) + var stateKey = $":before:// {fsql.GetEntityKeyString(entityType, entityBefore, false)}"; + if (ignores.TryGetValue(entityType, out var stateKeys) == false) ignores.Add(entityType, stateKeys = new Dictionary()); + if (stateKeys.ContainsKey(stateKey)) return; + stateKeys.Add(stateKey, true); + } + if (entityAfter != null) { - if (col.Attribute.IsVersion) continue; - var propvalBefore = table.GetPropertyValue(entityBefore, col.CsName); - var propvalAfter = table.GetPropertyValue(entityBefore, col.CsName); - if (propvalBefore != propvalAfter) changes.Add(col.CsName); - continue; + var stateKey = $":after:// {fsql.GetEntityKeyString(entityType, entityAfter, false)}"; + if (ignores.TryGetValue(entityType, out var stateKeys) == false) ignores.Add(entityType, stateKeys = new Dictionary()); + if (stateKeys.ContainsKey(stateKey)) return; + stateKeys.Add(stateKey, true); + } + + var table = fsql.CodeFirst.GetTableByEntity(entityType); + if (table == null) return; + if (entityBefore == null && entityAfter == null) return; + if (entityBefore == null && entityAfter != null) + { + insertLog.Add(NativeTuple.Create(entityType, entityAfter)); + return; + } + if (entityBefore != null && entityAfter == null) + { + deleteLog.Add(NativeTuple.Create(entityType, entityBefore)); + NavigateReader(fsql, entityType, entityBefore, (path, tr, ct, stackvs) => + { + deleteLog.Add(NativeTuple.Create(ct, stackvs.First())); + }); + return; + } + var changes = new List(); + foreach (var col in table.ColumnsByCs.Values) + { + if (table.ColumnsByCsIgnore.ContainsKey(col.CsName)) continue; + if (table.ColumnsByCs.ContainsKey(col.CsName)) + { + if (col.Attribute.IsVersion) continue; + var propvalBefore = table.GetPropertyValue(entityBefore, col.CsName); + var propvalAfter = table.GetPropertyValue(entityAfter, col.CsName); + if (object.Equals(propvalBefore, propvalAfter) == false) changes.Add(col.CsName); + continue; + } + } + if (changes.Any()) + updateLog.Add(NativeTuple.Create(entityType, entityBefore, entityAfter, changes)); + + foreach (var prop in table.Properties.Values) + { + var tbref = table.GetTableRef(prop.Name, false); + if (tbref == null) continue; + if (navigatePropertyName != null && prop.Name != navigatePropertyName) continue; + var propvalBefore = table.GetPropertyValue(entityBefore, prop.Name); + var propvalAfter = table.GetPropertyValue(entityAfter, prop.Name); + switch (tbref.RefType) + { + case TableRefType.OneToOne: + LocalCompareEntityValue(tbref.RefEntityType, propvalBefore, propvalAfter, null); + break; + case TableRefType.OneToMany: + LocalCompareEntityValueCollection(tbref, propvalBefore as IEnumerable, propvalAfter as IEnumerable); + break; + case TableRefType.ManyToMany: + var middleValuesBefore = GetManyToManyObjects(fsql, table, tbref, entityBefore, prop); + var middleValuesAfter = GetManyToManyObjects(fsql, table, tbref, entityAfter, prop); + LocalCompareEntityValueCollection(tbref, middleValuesBefore as IEnumerable, middleValuesAfter as IEnumerable); + break; + case TableRefType.PgArrayToMany: + case TableRefType.ManyToOne: //不属于聚合根 + break; + } } } - if (changes.Any()) - updateLog.Add(NativeTuple.Create(entityType, entityBefore, entityAfter, changes)); - - foreach (var prop in table.Properties.Values) - { - var tbref = table.GetTableRef(prop.Name, false); - if (tbref == null) continue; - if (navigatePropertyName != null && prop.Name != navigatePropertyName) continue; - var propvalBefore = table.GetPropertyValue(entityBefore, prop.Name); - var propvalAfter = table.GetPropertyValue(entityBefore, prop.Name); - switch (tbref.RefType) - { - case TableRefType.OneToOne: - CompareEntityValue(fsql, tbref.RefEntityType, propvalBefore, propvalAfter, null, insertLog, updateLog, deleteLog); - break; - case TableRefType.OneToMany: - LocalCompareEntityValueCollection(tbref, propvalBefore as IEnumerable, propvalAfter as IEnumerable); - break; - case TableRefType.ManyToMany: - var middleValuesBefore = GetManyToManyObjects(fsql, table, tbref, entityBefore, prop); - var middleValuesAfter = GetManyToManyObjects(fsql, table, tbref, entityAfter, prop); - LocalCompareEntityValueCollection(tbref, middleValuesBefore as IEnumerable, middleValuesAfter as IEnumerable); - break; - case TableRefType.PgArrayToMany: - case TableRefType.ManyToOne: //不属于聚合根 - break; - } - } - void LocalCompareEntityValueCollection(TableRef tbref, IEnumerable collectionBefore, IEnumerable collectionAfter) { var elementType = tbref.RefType == TableRefType.ManyToMany ? tbref.RefMiddleEntityType : tbref.RefEntityType; @@ -133,7 +156,7 @@ static class AggregateRootUtils } } foreach (var key in dictBefore.Keys) - CompareEntityValue(fsql, elementType, dictBefore[key], dictAfter[key], null, insertLog, updateLog, deleteLog); + LocalCompareEntityValue(elementType, dictBefore[key], dictAfter[key], null); } } diff --git a/FreeSql.Tests/FreeSql.Tests.DbContext2/AggregateRootRepositoryTest.cs b/FreeSql.Tests/FreeSql.Tests.DbContext2/AggregateRootRepositoryTest.cs index 89dd09b0..46a233de 100644 --- a/FreeSql.Tests/FreeSql.Tests.DbContext2/AggregateRootRepositoryTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.DbContext2/AggregateRootRepositoryTest.cs @@ -78,6 +78,9 @@ namespace FreeSql.Tests.DbContext2 Assert.NotNull(users[1].Ext); Assert.Equal(3, users[1].Ext.UserId); Assert.Equal("admin03_remark", users[1].Ext.Remark); + + user.Ext.Remark = "admin01_remark changed01"; + repo.Update(user); } } class User