Skip to content

Instantly share code, notes, and snippets.

@rodion-m
Created June 24, 2025 18:03
Show Gist options
  • Select an option

  • Save rodion-m/933e987f965a9ea190d402f2210afa97 to your computer and use it in GitHub Desktop.

Select an option

Save rodion-m/933e987f965a9ea190d402f2210afa97 to your computer and use it in GitHub Desktop.
Ответ CodeAlive про дубли

почему у нас дублируются Identifier артефактов в базе? мы же вроде защищены от этого в TryAddArtifact?

Ответ CodeAlive

Вы задали очень хороший вопрос. Ваше предположение о том, что TryAddArtifact должен предотвращать дубликаты, верно, но только в определенном контексте. Давайте разберемся, почему дубликаты все же могут появляться в базе данных.

Проблема заключается не в самом TryAddArtifact, а в том, на основе чего он проверяет уникальность.

Как работает TryAddArtifact

Метод TryAddArtifact находится в ArtifactsMapper и использует HashSet<ArtifactAggregate> для предотвращения добавления дубликатов в локальную коллекцию, которая будет отправлена в базу данных одной пачкой.

// src/CodeAlive.LSP/Mapping/ArtifactsMapper.cs:26
HashSet<ArtifactAggregate> artifactsToSave = new();
void TryAddArtifact(ArtifactAggregate artifact)
{
    if (artifactsToSave.Add(artifact) == false)
    {
        logger.LogWarning("Artifact {ArtifactId} already exists", artifact.Identifier);
    }
}

Работа HashSet.Add() зависит от методов Equals() и GetHashCode() класса ArtifactAggregate. Посмотрим на их реализацию:

// src/CodeAlive.Domain/CoreModels/ArtifactAggregate.cs:148
private bool Equals(ArtifactAggregate other)
{
    return Id.Equals(other.Id);
}

// src/CodeAlive.Domain/CoreModels/ArtifactAggregate.cs:167
public override int GetHashCode()
{
    // ReSharper disable once NonReadonlyMemberInGetHashCode
    return Id.GetHashCode();
}

Как видите, HashSet проверяет уникальность по свойству Id, которое является ObjectId для MongoDB, а не по логическому идентификатору Identifier (ArtifactId).

Итог: TryAddArtifact защищает от дубликатов только в рамках одной операции сохранения и только если ObjectId одинаковый. Проблема дублирования в базе данных почти наверняка вызвана несогласованной генерацией строковых значений для ArtifactId в разных частях системы или при разных запусках, что приводит к генерации разных ObjectId и, как следствие, к созданию новых записей в базе вместо обновления существующих.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment