Уникальная проверка Entity Framework на локальном компьютере и в базе данных

StackOverflow https://stackoverflow.com//questions/22051297

Вопрос

В настоящее время я пытаюсь обрабатывать уникальную проверку сущностей как часть моего метода ValidateEntity в моем DbContext.Проблема, которую я пытаюсь решить, заключается в том, что при одновременном добавлении нескольких объектов обнаруживаются уникальные ошибки ограничений до того, как они попадут в базу данных.Примером может служить случай, когда при добавлении объектов A и B необходимо убедиться, что A и B не имеют одинаковых имен.В настоящее время у меня применены уникальные индексы, так что, по крайней мере, база данных справится с этим, и у меня есть следующий код, который может охватывать случаи, когда A уже находится в базе данных:

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."));
}

Есть ли что-нибудь проще, чем сделать следующее?

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."));
}

Редактировать

Случай, когда «уникальный ключ» состоит из внешнего ключа, представляет собой более сложную ситуацию.При работе с базой данных вам необходимо использовать поле внешнего ключа, хотя при работе с локальным кешем вы не всегда можете сказать, когда ReferenceId == ReferenceId поскольку они оба равны нулю, если ссылочные объекты также были только что добавлены.Будет ли правильный способ проверки локального кеша следующим, или мне нужно будет сразу загрузить ссылку, поскольку во время проверки отложенная загрузка отключена?

this.Components.Local.Any(x => x != item && x.Name == item.Name && x.ReferenceId == item.ReferenceId && x.Reference == item.Reference)
Это было полезно?

Решение

Чтобы решить мою проблему и ограничить повторное использование, я добавил следующие расширения, чтобы помочь с уникальной проверкой.

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;
}

Вторая функция касается случая, когда уникальный ключ состоит из ссылок на внешние ключи.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top