Создает ли DbContext.addAsync генерирует исключение с учетом повторяющегося уникального индекса?

#entity-framework-core

#entity-framework-core

Вопрос:

Я написал следующий код, чтобы добавить пользователя в базу данных, и я сомневаюсь в необходимости проверки существующего электронного письма (уникального ключа) перед добавлением человека.

Будет ли addAsync выдавать исключение для меня, если я попытаюсь добавить пользователя с тем же адресом электронной почты, что и существующий пользователь?

Я включил MVCE, включающий мою службу, репозиторий и DbContext, но на самом деле это касается только поведения одного вызова и того, вызывает ли он исключение. Если да, то что это за исключение?

 namespace Project
{
    public sealed class PersonService
    {
        private readonly PersonRepository personRepository;

        public PersonService(PersonRepository personRepository)
        {
            this.personRepository = personRepository;
        }

        public async Task<Person> AddAsync(Person person)
        {
            var existingPerson = await this.personRepository.GetByEmailAsync(person.Email);

            if (existingPerson != null)
            {
                throw new DuplicateEmailException(person.Email, $"The Email {person.Email} is already taken.");
            }

            await this.personRepository.AddAsync(person);

            return person;
        }
    }

    public sealed class PersonRepository
    {
        private readonly ProjectDbContext dbContext;

        public PersonRepository(ProjectDbContext dbContext)
        {
            this.dbContext = dbContext;
        }

        public async Task<Person> GetByEmailAsync(string email)
        {
            return await this.dbContext.Person
                .FirstOrDefaultAsync(p => p.Email == email);
        }

        public async Task AddAsync(Person person)
        {
            if (person == null)
            {
                return;
            }

            await this.dbContext.AddAsync(person);
            await this.dbContext.SaveChangesAsync();
        }
    }

    public sealed class ProjectDbContext : DbContext
    {
        public ProjectDbContext(DbContextOptions options)
            : base(options)
        {
        }

        public DbSet<Person> Person { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<Person>()
                .Property(p => p.Email)
                .IsRequired();

            modelBuilder.Entity<Person>()
                .HasIndex(p => new { p.Email })
                .IsUnique();
        }
    }
}
  

Ответ №1:

Я ставлю под сомнение необходимость проверки существующего электронного письма (уникального ключа) перед добавлением человека. Выдаст ли AddAsync исключение для меня, если я попытаюсь добавить пользователя с тем же адресом электронной почты, что и существующий пользователь?

dbContext.AddAsync(person) не будет выдавать никакой ошибки, но при _dbContext.SaveChanges(); вызове будет выдано следующее исключение:

Исключение SQLException: невозможно вставить дублирующуюся строку ключа в dbo объекта.Лица’ с уникальным индексом ‘IX_Perosns_Email’. Значение повторяющегося ключа равно (foo@gmail.com ). Оператор был завершен.

Поэтому вам следует проверить / проверить это на уровне контроллера или модели, а не в вашем PersonService.AddAsync() методе обслуживания, чтобы вы могли показать конечному пользователю правильное сообщение об ошибке проверки.