mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-12-20 00:25:48 +08:00
AggregateRootRepository Boundary
This commit is contained in:
@@ -25,7 +25,7 @@ namespace FreeSql
|
||||
var repos = new Dictionary<Type, object>();
|
||||
try
|
||||
{
|
||||
var ret = await InsertWithinBoundaryStaticAsync(_boundaryName, _repository, GetChildRepository, entitys, out var affrows, cancellationToken);
|
||||
var ret = await InsertWithinBoundaryStaticAsync(_boundaryName, _repository, GetChildRepository, entitys, null, cancellationToken);
|
||||
Attach(ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -35,9 +35,116 @@ namespace FreeSql
|
||||
_repository.FlushState();
|
||||
}
|
||||
}
|
||||
Task<List<T1>> InsertWithinBoundaryStaticAsync<T1>(string boundaryName, IBaseRepository<T1> rootRepository, Func<Type, IBaseRepository<object>> getChildRepository, IEnumerable<T1> rootEntitys, out int affrows, CancellationToken cancellationToken) where T1 : class
|
||||
async Task<List<T1>> InsertWithinBoundaryStaticAsync<T1>(string boundaryName, IBaseRepository<T1> rootRepository, Func<Type, IBaseRepository<object>> getChildRepository, IEnumerable<T1> rootEntitys, int[] affrows, CancellationToken cancellationToken) where T1 : class
|
||||
{
|
||||
return Task.FromResult(InsertWithinBoundaryStatic(boundaryName, rootRepository, getChildRepository, rootEntitys, out affrows));
|
||||
Dictionary<Type, Dictionary<string, bool>> ignores = new Dictionary<Type, Dictionary<string, bool>>();
|
||||
Dictionary<Type, IBaseRepository<object>> repos = new Dictionary<Type, IBaseRepository<object>>();
|
||||
var localAffrows = 0;
|
||||
try
|
||||
{
|
||||
return await LocalInsertAsync(rootRepository, rootEntitys, true);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (affrows != null) affrows[0] = localAffrows;
|
||||
}
|
||||
|
||||
bool LocalCanInsert(Type entityType, object entity, bool isadd)
|
||||
{
|
||||
var stateKey = rootRepository.Orm.GetEntityKeyString(entityType, entity, false);
|
||||
if (stateKey == null) return true;
|
||||
if (ignores.TryGetValue(entityType, out var stateKeys) == false)
|
||||
{
|
||||
if (isadd)
|
||||
{
|
||||
ignores.Add(entityType, stateKeys = new Dictionary<string, bool>());
|
||||
stateKeys.Add(stateKey, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (stateKeys.ContainsKey(stateKey) == false)
|
||||
{
|
||||
if (isadd) stateKeys.Add(stateKey, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
async Task<List<T2>> LocalInsertAsync<T2>(IBaseRepository<T2> repository, IEnumerable<T2> entitys, bool cascade) where T2 : class
|
||||
{
|
||||
var table = repository.Orm.CodeFirst.GetTableByEntity(repository.EntityType);
|
||||
if (table.Primarys.Any(col => col.Attribute.IsIdentity))
|
||||
{
|
||||
foreach (var entity in entitys)
|
||||
repository.Orm.ClearEntityPrimaryValueWithIdentity(repository.EntityType, entity);
|
||||
}
|
||||
var ret = await repository.InsertAsync(entitys, cancellationToken);
|
||||
localAffrows += ret.Count;
|
||||
foreach (var entity in entitys) LocalCanInsert(repository.EntityType, entity, true);
|
||||
if (cascade == false) return ret;
|
||||
|
||||
foreach (var tr in table.GetAllTableRef().OrderBy(a => a.Value.RefType).ThenBy(a => a.Key))
|
||||
{
|
||||
var tbref = tr.Value;
|
||||
if (tbref.Exception != null) continue;
|
||||
if (table.Properties.TryGetValue(tr.Key, out var prop) == false) continue;
|
||||
var boundaryAttr = AggregateRootUtils.GetPropertyBoundaryAttribute(prop, boundaryName);
|
||||
if (boundaryAttr?.Break == true) continue;
|
||||
switch (tbref.RefType)
|
||||
{
|
||||
case TableRefType.OneToOne:
|
||||
var otoList = ret.Select(entity =>
|
||||
{
|
||||
var otoItem = table.GetPropertyValue(entity, prop.Name);
|
||||
if (LocalCanInsert(tbref.RefEntityType, otoItem, false) == false) return null;
|
||||
AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otoItem);
|
||||
return otoItem;
|
||||
}).Where(entity => entity != null).ToArray();
|
||||
if (otoList.Any())
|
||||
{
|
||||
var repo = getChildRepository(tbref.RefEntityType);
|
||||
await LocalInsertAsync(repo, otoList, boundaryAttr?.BreakThen != true);
|
||||
}
|
||||
break;
|
||||
case TableRefType.OneToMany:
|
||||
var otmList = ret.Select(entity =>
|
||||
{
|
||||
var otmEach = table.GetPropertyValue(entity, prop.Name) as IEnumerable;
|
||||
if (otmEach == null) return null;
|
||||
var otmItems = new List<object>();
|
||||
foreach (var otmItem in otmEach)
|
||||
{
|
||||
if (LocalCanInsert(tbref.RefEntityType, otmItem, false) == false) continue;
|
||||
otmItems.Add(otmItem);
|
||||
}
|
||||
AggregateRootUtils.SetNavigateRelationshipValue(repository.Orm, tbref, table.Type, entity, otmItems);
|
||||
return otmItems;
|
||||
}).Where(entity => entity != null).SelectMany(entity => entity).ToArray();
|
||||
if (otmList.Any())
|
||||
{
|
||||
var repo = getChildRepository(tbref.RefEntityType);
|
||||
await LocalInsertAsync(repo, otmList, boundaryAttr?.BreakThen != true);
|
||||
}
|
||||
break;
|
||||
case TableRefType.ManyToMany:
|
||||
var mtmMidList = new List<object>();
|
||||
ret.ForEach(entity =>
|
||||
{
|
||||
var mids = AggregateRootUtils.GetManyToManyObjects(repository.Orm, table, tbref, entity, prop);
|
||||
if (mids != null) mtmMidList.AddRange(mids);
|
||||
});
|
||||
if (mtmMidList.Any())
|
||||
{
|
||||
var repo = getChildRepository(tbref.RefMiddleEntityType);
|
||||
await LocalInsertAsync(repo, mtmMidList, false);
|
||||
}
|
||||
break;
|
||||
case TableRefType.PgArrayToMany:
|
||||
case TableRefType.ManyToOne: //ManyToOne、ManyToMany外部表、PgArrayToMany 不属于聚合根成员,可以查询,不能增删改
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -138,8 +245,9 @@ namespace FreeSql
|
||||
foreach (var il in insertLogDict)
|
||||
{
|
||||
var repo = GetChildRepository(il.Key);
|
||||
await InsertWithinBoundaryStaticAsync(_boundaryName, repo, GetChildRepository, il.Value, out var affrowsOut, cancellationToken);
|
||||
affrows += affrowsOut;
|
||||
var affrowsOut = new int[1];
|
||||
await InsertWithinBoundaryStaticAsync(_boundaryName, repo, GetChildRepository, il.Value, affrowsOut, cancellationToken);
|
||||
affrows += affrowsOut[0];
|
||||
}
|
||||
|
||||
for (var a = tracking.DeleteLog.Count - 1; a >= 0; a--)
|
||||
|
||||
Reference in New Issue
Block a user