Question

J'essaie actuellement de gérer une validation unique pour les entités dans le cadre de ma méthode de validation sur mon DBContext. Le problème que j'essaie de résoudre est lorsque vous ajoutez plusieurs entités simultanément détectant les erreurs de contrainte uniques avant qu'elle ne frappe la base de données. Un exemple est le cas lors de l'ajout d'une entité A et B en veillant à ce que A et B n'ont pas le même nom. Actuellement, j'ai les index uniques appliqués, donc au moins la base de données le gérera, et j'ai le code suivant qui peut couvrir lorsque A est déjà dans la base de données:

if (this.Components.Any(x => x.Id != item.Id && x.Name == item.Name))
{
    result.ValidationErrors.Add(new DbValidationError("Name", "There already exists another component with that name."));
}

Y a-t-il quelque chose de plus simple que de faire ce qui suit alors?

Expression<Func<Component, bool>> predicate = x => x.Name == item.Name;

if (this.Components.Where(x => x.Id != item.Id).Any(predicate) || this.Components.Local.Where(x => x != item).Any(predicate.Compile()))
{
    result.ValidationErrors.Add(new DbValidationError("Name", "There already exists another component with that name."));
}

Modifier

Le cas lorsque la "clé unique" est composée d'une clé étrangère est une situation plus complexe. Lorsque vous allez contre la base de données, vous devez utiliser le champ de la clé étranger, cependant, lorsque vous allez à l'encontre du cache local, vous ne pouvez pas toujours dire quand ReferenceId == ReferenceId en raison d'eux étant zéro si les entités de référence étaient également simplement ajoutées. Serait la bonne façon de vérifier que le cache local soit les suivants ou devrais-je avoir besoin de charger la référence depuis lors lors de la validation de chargement paresseux est désactivé?

this.Components.Local.Any(x => x != item && x.Name == item.Name && x.ReferenceId == item.ReferenceId && x.Reference == item.Reference)

Était-ce utile?

La solution

Pour résoudre mon problème et limiter la réutilisation, j'ai ajouté les extensions suivantes pour aider à une validation unique.

public static bool UniqueCheck<TSource>(this DbSet<TSource> set, TSource item, Expression<Func<TSource, bool>> uniquePredicate) where TSource : class, IAuditEntity
{

    var function = uniquePredicate.Compile();

    var localContains = set.Local.Where(x => x != item).Any(function);
    if (localContains) return localContains;

    var remoteContains = set.Where(x => x.Id != item.Id).Any(uniquePredicate);

    return remoteContains;
}

public static bool UniqueCheckWithReference<TSource>(this DbSet<TSource> set, TSource item, Expression<Func<TSource, bool>> uniquePredicate, Expression<Func<TSource, bool>> referenceUniquePredicate) where TSource : class, IAuditEntity
{
    var localContains = set.Local.Where(x => x != item).Where(uniquePredicate.Compile()).Where(referenceUniquePredicate.Compile()).Any();
    if (localContains) return localContains;

    var remoteContains = set.Where(x => x.Id != item.Id).Where(uniquePredicate);

    return false;
}

La deuxième fonction traite du cas de la clé unique en étant faite de références de clés étrangères.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top