fix(dal): UnitFilter восставновлена логика по фильтрации свзяанных ЭК, в части работы параметра IsFullMatch
This commit is contained in:
@@ -340,8 +340,7 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
private async Task<List<FilteredUnitContext>> ApplyRelationshipFiltersOnDbAsync(
|
private async Task<List<FilteredUnitContext>> ApplyRelationshipFiltersOnDbAsync(
|
||||||
List<Guid> unitIds,
|
List<Guid> unitIds,
|
||||||
IEnumerable<JobRelationshipFilter> relationshipFilters,
|
IEnumerable<JobRelationshipFilter> relationshipFilters,
|
||||||
CancellationToken cancellationToken = default
|
CancellationToken cancellationToken = default)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!relationshipFilters.Any() || !unitIds.Any())
|
if (!relationshipFilters.Any() || !unitIds.Any())
|
||||||
{
|
{
|
||||||
@@ -353,178 +352,87 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
logger.LogDebug("ApplyRelationshipFiltersOnDbAsync: вход {UnitCount} юнитов, фильтров: {FilterCount}",
|
logger.LogDebug("ApplyRelationshipFiltersOnDbAsync: вход {UnitCount} юнитов, фильтров: {FilterCount}",
|
||||||
unitIds.Count, relationshipFilters.Count());
|
unitIds.Count, relationshipFilters.Count());
|
||||||
|
|
||||||
#if DEBUG
|
var resultContexts = unitIds.ToDictionary(id => id, id => new FilteredUnitContext { UnitId = id });
|
||||||
if (unitIds.Contains(targetUnitId))
|
|
||||||
{
|
|
||||||
logger.LogDebug("DEBUG: Юнит {TargetUnitId} присутствует во входных данных ApplyRelationshipFiltersOnDbAsync", targetUnitId);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var parentRelFilters = relationshipFilters.Where(rf => rf.IsParent).ToList();
|
var parentRelFilters = relationshipFilters.Where(rf => rf.IsParent).ToList();
|
||||||
var childRelFilters = relationshipFilters.Where(rf => !rf.IsParent).ToList();
|
var childRelFilters = relationshipFilters.Where(rf => !rf.IsParent).ToList();
|
||||||
|
|
||||||
var resultContexts = unitIds.ToDictionary(id => id, id => new FilteredUnitContext { UnitId = id });
|
|
||||||
|
|
||||||
// Обработка родительских фильтров
|
// Обработка родительских фильтров
|
||||||
if (parentRelFilters.Any())
|
if (parentRelFilters.Any())
|
||||||
{
|
{
|
||||||
logger.LogDebug(" Родительские фильтры ({Count}):", parentRelFilters.Count);
|
await ApplyRelationshipFiltersAsync(
|
||||||
|
unitIds,
|
||||||
var allParentLinks = await unitInUnitService.Get()
|
resultContexts, // ← Передаём словарь, а не список
|
||||||
.AsNoTracking()
|
parentRelFilters,
|
||||||
.Where(link => unitIds.Contains(link.ChildUnitId))
|
isParentDirection: true,
|
||||||
.Select(link => new { ChildId = link.ChildUnitId, ParentId = link.ParentUnitId })
|
cancellationToken);
|
||||||
.ToListAsync(cancellationToken);
|
|
||||||
|
|
||||||
var allParentIds = allParentLinks.Select(l => l.ParentId).Distinct().ToList();
|
|
||||||
logger.LogDebug(" Найдено {ParentCount} уникальных родителей для {LinkCount} связей",
|
|
||||||
allParentIds.Count, allParentLinks.Count);
|
|
||||||
|
|
||||||
var validParentIds = new HashSet<Guid>(allParentIds);
|
|
||||||
logger.LogDebug(" Начальное количество родителей: {Count}", validParentIds.Count);
|
|
||||||
|
|
||||||
foreach (var relFilter in parentRelFilters)
|
|
||||||
{
|
|
||||||
var valueMask = relFilter.ValueMask?.Trim();
|
|
||||||
if (string.IsNullOrWhiteSpace(valueMask))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
|
||||||
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
|
||||||
string dbValueMask;
|
|
||||||
if (isStartsWith && isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.Trim('%')}%";
|
|
||||||
else if (isStartsWith)
|
|
||||||
dbValueMask = $"{valueMask.TrimEnd('%')}%";
|
|
||||||
else if (isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.TrimStart('%')}";
|
|
||||||
else
|
|
||||||
dbValueMask = valueMask;
|
|
||||||
|
|
||||||
var fieldName = relFilter.UnitField?.AihitName ?? $"FieldId={relFilter.FieldId}";
|
|
||||||
logger.LogDebug(" RelationshipFilter (Parent): Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}, IsFullMatch={IsFullMatch}",
|
|
||||||
fieldName, dbValueMask, relFilter.IsInverse, relFilter.IsFullMatch);
|
|
||||||
|
|
||||||
var matchingParents = await unitService.Get()
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(u => allParentIds.Contains(u.Id))
|
|
||||||
.Where(u => u.UnitValues.Any(v =>
|
|
||||||
v.FieldId == relFilter.FieldId &&
|
|
||||||
EF.Functions.Like(v.Value.Value, dbValueMask)))
|
|
||||||
.Select(u => u.Id)
|
|
||||||
.ToListAsync(cancellationToken);
|
|
||||||
|
|
||||||
logger.LogDebug(" Найдено {MatchCount} родителей по маске", matchingParents.Count);
|
|
||||||
|
|
||||||
if (relFilter.IsInverse)
|
|
||||||
{
|
|
||||||
validParentIds.ExceptWith(matchingParents);
|
|
||||||
logger.LogDebug(" IsInverse=true → исключены {ExcludedCount} родителей, осталось {RemainingCount}",
|
|
||||||
matchingParents.Count, validParentIds.Count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
validParentIds.IntersectWith(matchingParents);
|
|
||||||
logger.LogDebug(" IsInverse=false → оставлены {KeptCount} родителей",
|
|
||||||
validParentIds.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сопоставляем подходящих родителей с их детьми
|
|
||||||
foreach (var link in allParentLinks)
|
|
||||||
{
|
|
||||||
if (validParentIds.Contains(link.ParentId))
|
|
||||||
{
|
|
||||||
resultContexts[link.ChildId].ValidParentIds.Add(link.ParentId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalParentsAdded = resultContexts.Values.Sum(c => c.ValidParentIds.Count);
|
|
||||||
logger.LogDebug(" Добавлено {TotalParents} родительских связей для {UnitCount} юнитов",
|
|
||||||
totalParentsAdded, resultContexts.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обработка дочерних фильтров
|
// Обработка дочерних фильтров
|
||||||
if (childRelFilters.Any())
|
if (childRelFilters.Any())
|
||||||
{
|
{
|
||||||
logger.LogDebug(" Дочерние фильтры ({Count}):", childRelFilters.Count);
|
await ApplyRelationshipFiltersAsync(
|
||||||
|
unitIds,
|
||||||
var allChildLinks = await unitInUnitService.Get()
|
resultContexts, // ← Передаём словарь, а не список
|
||||||
.AsNoTracking()
|
childRelFilters,
|
||||||
.Where(link => unitIds.Contains(link.ParentUnitId))
|
isParentDirection: false,
|
||||||
.Select(link => new { ParentId = link.ParentUnitId, ChildId = link.ChildUnitId })
|
cancellationToken);
|
||||||
.ToListAsync(cancellationToken);
|
|
||||||
|
|
||||||
var allChildIds = allChildLinks.Select(l => l.ChildId).Distinct().ToList();
|
|
||||||
logger.LogDebug(" Найдено {ChildCount} уникальных детей для {LinkCount} связей",
|
|
||||||
allChildIds.Count, allChildLinks.Count);
|
|
||||||
|
|
||||||
var validChildIds = new HashSet<Guid>(allChildIds);
|
|
||||||
logger.LogDebug(" Начальное количество детей: {Count}", validChildIds.Count);
|
|
||||||
|
|
||||||
foreach (var relFilter in childRelFilters)
|
|
||||||
{
|
|
||||||
var valueMask = relFilter.ValueMask?.Trim();
|
|
||||||
if (string.IsNullOrWhiteSpace(valueMask))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
|
||||||
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
|
||||||
string dbValueMask;
|
|
||||||
if (isStartsWith && isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.Trim('%')}%";
|
|
||||||
else if (isStartsWith)
|
|
||||||
dbValueMask = $"{valueMask.TrimEnd('%')}%";
|
|
||||||
else if (isEndsWith)
|
|
||||||
dbValueMask = $"%{valueMask.TrimStart('%')}";
|
|
||||||
else
|
|
||||||
dbValueMask = valueMask;
|
|
||||||
|
|
||||||
var fieldName = relFilter.UnitField?.AihitName ?? $"FieldId={relFilter.FieldId}";
|
|
||||||
logger.LogDebug(" RelationshipFilter (Child): Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}, IsFullMatch={IsFullMatch}",
|
|
||||||
fieldName, dbValueMask, relFilter.IsInverse, relFilter.IsFullMatch);
|
|
||||||
|
|
||||||
var matchingChildren = await unitService.Get()
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(u => allChildIds.Contains(u.Id))
|
|
||||||
.Where(u => u.UnitValues.Any(v =>
|
|
||||||
v.FieldId == relFilter.FieldId &&
|
|
||||||
EF.Functions.Like(v.Value.Value, dbValueMask)))
|
|
||||||
.Select(u => u.Id)
|
|
||||||
.ToListAsync(cancellationToken);
|
|
||||||
|
|
||||||
logger.LogDebug(" Найдено {MatchCount} детей по маске", matchingChildren.Count);
|
|
||||||
|
|
||||||
if (relFilter.IsInverse)
|
|
||||||
{
|
|
||||||
validChildIds.ExceptWith(matchingChildren);
|
|
||||||
logger.LogDebug(" IsInverse=true → исключены {ExcludedCount} детей, осталось {RemainingCount}",
|
|
||||||
matchingChildren.Count, validChildIds.Count);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
validChildIds.IntersectWith(matchingChildren);
|
|
||||||
logger.LogDebug(" IsInverse=false → оставлены {KeptCount} детей",
|
|
||||||
validChildIds.Count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Сопоставляем подходящих детей с их родителями
|
|
||||||
foreach (var link in allChildLinks)
|
|
||||||
{
|
|
||||||
if (validChildIds.Contains(link.ChildId))
|
|
||||||
{
|
|
||||||
resultContexts[link.ParentId].ValidChildIds.Add(link.ChildId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var totalChildrenAdded = resultContexts.Values.Sum(c => c.ValidChildIds.Count);
|
|
||||||
logger.LogDebug(" Добавлено {TotalChildren} дочерних связей для {UnitCount} юнитов",
|
|
||||||
totalChildrenAdded, resultContexts.Count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = resultContexts.Values.ToList();
|
// Если фильтры были — оставляем только юниты со связями
|
||||||
logger.LogDebug("ApplyRelationshipFiltersOnDbAsync: выход {ContextCount} контекстов", result.Count);
|
// Если фильтров не было — оставляем все юниты
|
||||||
|
bool hasRelationshipFilters = parentRelFilters.Any() || childRelFilters.Any();
|
||||||
|
|
||||||
|
var unitsWithRelationships = hasRelationshipFilters
|
||||||
|
? resultContexts.Values.Where(c => c.ValidParentIds.Any() || c.ValidChildIds.Any()).ToList()
|
||||||
|
: resultContexts.Values.ToList();
|
||||||
|
|
||||||
|
var result = unitsWithRelationships;
|
||||||
|
logger.LogDebug("ApplyRelationshipFiltersOnDbAsync: выход {ContextCount} контекстов (из {InitialCount})",
|
||||||
|
result.Count, resultContexts.Count);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
foreach (var context in result)
|
||||||
|
{
|
||||||
|
var u = await unitService.GetAsync(context.UnitId);
|
||||||
|
|
||||||
|
if (u == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logger.LogDebug("Найден ЭК {UnitName}", u.Name);
|
||||||
|
|
||||||
|
if (context.ValidParentIds.Any())
|
||||||
|
{
|
||||||
|
|
||||||
|
var parents = context.ValidParentIds;
|
||||||
|
|
||||||
|
logger.LogDebug("\tФильтрам соответствуют {ParentsCount} родителей:", parents.Count);
|
||||||
|
|
||||||
|
foreach (var parent in context.ValidParentIds)
|
||||||
|
{
|
||||||
|
var p = await unitService.GetAsync(parent);
|
||||||
|
|
||||||
|
logger.LogDebug("\t\t {ParentName};", p?.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.ValidChildIds.Any())
|
||||||
|
{
|
||||||
|
|
||||||
|
var children = context.ValidChildIds;
|
||||||
|
|
||||||
|
logger.LogDebug("\tФильтрам соответствуют {ParentsCount} детей:", children.Count);
|
||||||
|
|
||||||
|
foreach (var child in children)
|
||||||
|
{
|
||||||
|
var c = await unitService.GetAsync(child);
|
||||||
|
|
||||||
|
logger.LogDebug("\t\t {ChildName};", c?.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -694,7 +602,6 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async Task<List<string>> GetRelatedUnitNamesAsync(Guid jobId, Guid unitId, CancellationToken cancellationToken = default)
|
public async Task<List<string>> GetRelatedUnitNamesAsync(Guid jobId, Guid unitId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
logger.LogDebug("Начало GetRelatedUnitNamesAsync. JobId: {JobId}, UnitId: {UnitId}", jobId, unitId);
|
logger.LogDebug("Начало GetRelatedUnitNamesAsync. JobId: {JobId}, UnitId: {UnitId}", jobId, unitId);
|
||||||
@@ -785,6 +692,172 @@ internal class UnitFilterService : IUnitFilterService
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region вспомогательные методы
|
#region вспомогательные методы
|
||||||
|
/// <summary>
|
||||||
|
/// Оценивает, проходит ли юнит фильтр связей
|
||||||
|
/// </summary>
|
||||||
|
private bool EvaluateFilter(
|
||||||
|
List<Guid> unitRelations, // Все связи юнита (родители или дети)
|
||||||
|
List<Guid> matchingRelations, // Связи, которые соответствуют маске
|
||||||
|
bool isFullMatch, // Полное совпадение (All) или хотя бы одно (Any)
|
||||||
|
bool isInverse, // Обратный фильтр
|
||||||
|
bool hasRelations // Есть ли связи у юнита
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int matchingCount = unitRelations.Count(r => matchingRelations.Contains(r));
|
||||||
|
int totalCount = unitRelations.Count;
|
||||||
|
|
||||||
|
// Случай: нет связей в направлении
|
||||||
|
if (!hasRelations)
|
||||||
|
{
|
||||||
|
// Если IsInverse = true → юнит проходит (нет связей, которые нарушают)
|
||||||
|
// Если IsInverse = false → юнит не проходит (нет связей, которые соответствуют)
|
||||||
|
return isInverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Основная логика
|
||||||
|
if (isFullMatch)
|
||||||
|
{
|
||||||
|
// Все связи должны соответствовать
|
||||||
|
bool allMatch = matchingCount == totalCount;
|
||||||
|
|
||||||
|
if (isInverse)
|
||||||
|
//Все связи не соответствуют фильтру
|
||||||
|
return matchingCount == 0;
|
||||||
|
else
|
||||||
|
//Все связи соответствуют фильтру
|
||||||
|
return allMatch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Хотя бы одна связь должна соответствовать
|
||||||
|
return matchingCount > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Применяет фильтры к связям (родителям или детям)
|
||||||
|
/// </summary>
|
||||||
|
private async Task ApplyRelationshipFiltersAsync(
|
||||||
|
List<Guid> unitIds,
|
||||||
|
Dictionary<Guid, FilteredUnitContext> resultContexts,
|
||||||
|
List<JobRelationshipFilter> relFilters,
|
||||||
|
bool isParentDirection,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!relFilters.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
|
var directionName = isParentDirection ? "Родительские" : "Дочерние";
|
||||||
|
logger.LogDebug(" {Direction} фильтры ({Count}):", directionName, relFilters.Count);
|
||||||
|
|
||||||
|
// Получаем все связи в нужном направлении
|
||||||
|
var allLinks = await unitInUnitService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(link => isParentDirection
|
||||||
|
? unitIds.Contains(link.ChildUnitId)
|
||||||
|
: unitIds.Contains(link.ParentUnitId))
|
||||||
|
.Select(link => new
|
||||||
|
{
|
||||||
|
SourceId = isParentDirection ? link.ChildUnitId : link.ParentUnitId,
|
||||||
|
TargetId = isParentDirection ? link.ParentUnitId : link.ChildUnitId
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
var allTargetIds = allLinks.Select(l => l.TargetId).Distinct().ToList();
|
||||||
|
logger.LogDebug(" Найдено {TargetCount} уникальных {TargetType} для {LinkCount} связей",
|
||||||
|
allTargetIds.Count,
|
||||||
|
isParentDirection ? "родителей" : "детей",
|
||||||
|
allLinks.Count);
|
||||||
|
|
||||||
|
// Группируем связи по исходному юниту для быстрого доступа
|
||||||
|
var linksBySource = allLinks.GroupBy(l => l.SourceId)
|
||||||
|
.ToDictionary(g => g.Key, g => g.Select(l => l.TargetId).ToList());
|
||||||
|
|
||||||
|
// Обрабатываем каждый фильтр
|
||||||
|
foreach (var relFilter in relFilters)
|
||||||
|
{
|
||||||
|
var valueMask = relFilter.ValueMask?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(valueMask))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Обработка маски LIKE
|
||||||
|
bool isStartsWith = valueMask.EndsWith("%") && !valueMask.EndsWith("%%");
|
||||||
|
bool isEndsWith = valueMask.StartsWith("%") && !valueMask.StartsWith("%%");
|
||||||
|
string dbValueMask;
|
||||||
|
if (isStartsWith && isEndsWith)
|
||||||
|
dbValueMask = $"%{valueMask.Trim('%')}%";
|
||||||
|
else if (isStartsWith)
|
||||||
|
dbValueMask = $"{valueMask.TrimEnd('%')}%";
|
||||||
|
else if (isEndsWith)
|
||||||
|
dbValueMask = $"%{valueMask.TrimStart('%')}";
|
||||||
|
else
|
||||||
|
dbValueMask = valueMask;
|
||||||
|
|
||||||
|
var fieldName = relFilter.UnitField?.AihitName ?? $"FieldId={relFilter.FieldId}";
|
||||||
|
logger.LogDebug(" RelationshipFilter ({Direction}): Поле='{FieldName}', Маска='{Mask}', IsInverse={IsInverse}, IsFullMatch={IsFullMatch}",
|
||||||
|
isParentDirection ? "Parent" : "Child",
|
||||||
|
fieldName, dbValueMask, relFilter.IsInverse, relFilter.IsFullMatch);
|
||||||
|
|
||||||
|
// Находим целевые юниты, которые соответствуют фильтру
|
||||||
|
var matchingTargetIds = await unitService.Get()
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(u => allTargetIds.Contains(u.Id))
|
||||||
|
.Where(u => u.UnitValues.Any(v =>
|
||||||
|
v.FieldId == relFilter.FieldId &&
|
||||||
|
EF.Functions.Like(v.Value.Value, dbValueMask)))
|
||||||
|
.Select(u => u.Id)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
logger.LogDebug(" Найдено {MatchCount} {TargetType} по маске",
|
||||||
|
matchingTargetIds.Count,
|
||||||
|
isParentDirection ? "родителей" : "детей");
|
||||||
|
|
||||||
|
// Применяем логику к каждому юниту
|
||||||
|
foreach (var context in resultContexts.Values)
|
||||||
|
{
|
||||||
|
var unitTargets = linksBySource.GetValueOrDefault(context.UnitId, new List<Guid>());
|
||||||
|
bool hasTargets = unitTargets.Any();
|
||||||
|
|
||||||
|
bool passesFilter = EvaluateFilter(
|
||||||
|
unitTargets,
|
||||||
|
matchingTargetIds,
|
||||||
|
relFilter.IsFullMatch,
|
||||||
|
relFilter.IsInverse,
|
||||||
|
hasTargets
|
||||||
|
);
|
||||||
|
|
||||||
|
if (passesFilter)
|
||||||
|
{
|
||||||
|
var validTargets = relFilter.IsInverse
|
||||||
|
? unitTargets.Except(matchingTargetIds)
|
||||||
|
: unitTargets.Intersect(matchingTargetIds);
|
||||||
|
|
||||||
|
if (isParentDirection)
|
||||||
|
context.ValidParentIds.UnionWith(validTargets);
|
||||||
|
else
|
||||||
|
context.ValidChildIds.UnionWith(validTargets);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Юнит не прошёл фильтр — очищаем его связи
|
||||||
|
if (isParentDirection)
|
||||||
|
context.ValidParentIds.Clear();
|
||||||
|
else
|
||||||
|
context.ValidChildIds.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalAdded = resultContexts.Sum(c =>
|
||||||
|
isParentDirection ? c.Value.ValidParentIds.Count : c.Value.ValidChildIds.Count);
|
||||||
|
|
||||||
|
logger.LogDebug(" Добавлено {Total} {TargetType} связей для {UnitCount} юнитов",
|
||||||
|
totalAdded,
|
||||||
|
isParentDirection ? "родительских" : "дочерних",
|
||||||
|
resultContexts.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task<List<Guid>> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter, CancellationToken cancellationToken = default)
|
private async Task<List<Guid>> GetUnitIdsFromCacheOrDbAsync(JobUnitFilter filter, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user