AggregateRootRepository

This commit is contained in:
2881099 2022-09-02 17:08:36 +08:00
parent ab9db8270d
commit 8162e21ce5
3 changed files with 85 additions and 57 deletions

View File

@ -36,7 +36,9 @@ namespace FreeSql
var repos = new Dictionary<Type, object>(); var repos = new Dictionary<Type, object>();
try try
{ {
return InsertAggregateRootStatic(_repository, GetChildRepository, entitys); var ret = InsertAggregateRootStatic(_repository, GetChildRepository, entitys);
Attach(ret);
return ret;
} }
finally finally
{ {

View File

@ -12,70 +12,93 @@ using System.Reflection;
static class AggregateRootUtils 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<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)
{ {
if (entityType == null) entityType = entityBefore?.GetType() ?? entityAfter?.GetType(); Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
var table = fsql.CodeFirst.GetTableByEntity(entityType); LocalCompareEntityValue(rootEntityType, rootEntityBefore, rootEntityAfter, rootNavigatePropertyName);
if (entityBefore == null && entityAfter == null) return; ignores.Clear();
if (entityBefore == null && entityAfter != null)
void LocalCompareEntityValue(Type entityType, object entityBefore, object entityAfter, string navigatePropertyName)
{ {
insertLog.Add(NativeTuple.Create(entityType, entityAfter)); if (entityType == null) entityType = entityBefore?.GetType() ?? entityAfter?.GetType();
return;
} if (entityBefore != null)
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())); var stateKey = $":before:// {fsql.GetEntityKeyString(entityType, entityBefore, false)}";
}); if (ignores.TryGetValue(entityType, out var stateKeys) == false) ignores.Add(entityType, stateKeys = new Dictionary<string, bool>());
return; if (stateKeys.ContainsKey(stateKey)) return;
} stateKeys.Add(stateKey, true);
var changes = new List<string>(); }
foreach (var col in table.ColumnsByCs.Values) if (entityAfter != null)
{
if (table.ColumnsByCsIgnore.ContainsKey(col.CsName)) continue;
if (table.ColumnsByCs.ContainsKey(col.CsName))
{ {
if (col.Attribute.IsVersion) continue; var stateKey = $":after:// {fsql.GetEntityKeyString(entityType, entityAfter, false)}";
var propvalBefore = table.GetPropertyValue(entityBefore, col.CsName); if (ignores.TryGetValue(entityType, out var stateKeys) == false) ignores.Add(entityType, stateKeys = new Dictionary<string, bool>());
var propvalAfter = table.GetPropertyValue(entityBefore, col.CsName); if (stateKeys.ContainsKey(stateKey)) return;
if (propvalBefore != propvalAfter) changes.Add(col.CsName); stateKeys.Add(stateKey, true);
continue; }
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<string>();
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) void LocalCompareEntityValueCollection(TableRef tbref, IEnumerable collectionBefore, IEnumerable collectionAfter)
{ {
var elementType = tbref.RefType == TableRefType.ManyToMany ? tbref.RefMiddleEntityType : tbref.RefEntityType; var elementType = tbref.RefType == TableRefType.ManyToMany ? tbref.RefMiddleEntityType : tbref.RefEntityType;
@ -133,7 +156,7 @@ static class AggregateRootUtils
} }
} }
foreach (var key in dictBefore.Keys) foreach (var key in dictBefore.Keys)
CompareEntityValue(fsql, elementType, dictBefore[key], dictAfter[key], null, insertLog, updateLog, deleteLog); LocalCompareEntityValue(elementType, dictBefore[key], dictAfter[key], null);
} }
} }

View File

@ -78,6 +78,9 @@ namespace FreeSql.Tests.DbContext2
Assert.NotNull(users[1].Ext); Assert.NotNull(users[1].Ext);
Assert.Equal(3, users[1].Ext.UserId); Assert.Equal(3, users[1].Ext.UserId);
Assert.Equal("admin03_remark", users[1].Ext.Remark); Assert.Equal("admin03_remark", users[1].Ext.Remark);
user.Ext.Remark = "admin01_remark changed01";
repo.Update(user);
} }
} }
class User class User