DbUpdateException при загрузке исходных данных

Я пытаюсь сделать проект приложения для отпуска, чтобы пройти курс обучения в колледже. Используя последние версии .net(8) и Entity Framework, я уже создал сущности, перечисления, базовые интерфейсы и т. д. В контроллере пока есть только метод create для класса person. Но у меня проблема с заполнением данных. Ниже приведены фрагменты кода из dbcontext, а также классы заполнения данных и скриншот из базы данных. Я пробовал разные варианты посева, но всегда где-то выдает ошибку.

Сообщение об ошибке:

Microsoft.EntityFrameworkCore.DbUpdateException: «Произошла ошибка при сохранении изменений сущности. Подробности смотрите во внутреннем исключении. SqlException: инструкция INSERT конфликтует с ограничением FOREIGN KEY «FK_People_Teams_Id». Конфликт произошел в базе данных «HolidayAppDb», таблица «dbo.Teams», столбец «TeamID».

Раздатчик людей, проблема возникает при сохранении от первого лица:

public async Task Seed()
{
    if (await _dbContext.Database.CanConnectAsync())
    {
        if (!_dbContext.HolidayRequests.Any())
        {
            var teamExists = await _dbContext.Teams.AnyAsync();
            if (!teamExists)
            {
                throw new Exception("The team does not exist.");
            }

            var approvedByFirstLeader = _dbContext.People.OrderBy(p => p.Id).First();
            var approvedBySecondLeader = _dbContext.People.OrderByDescending(p => p.Id).First();

            var firstPerson = new Person()
            {
                Id = Guid.NewGuid(),
                FirstName = "Jacek",
                LastName = "Magiera",
                DateOfBirth = new DateTime(1980, 1, 1),
                Position = "Developer",
                StartDate = new DateTime(2020, 1, 1),
                IsFullTime = true,
                ContactDetails = new()
                { City = "Warsaw", Street = "Miodowa", Email = "[email protected]", PhoneNumber = "+48878453875", PostalCode = "42-290" },
                HolidayTimeRemain = 10,
                TeamId = _dbContext.Teams.OrderBy(t => t.TeamID).First().TeamID,
                Team = _dbContext.Teams.OrderBy(t => t.TeamID).First()
            };

            _dbContext.People.Add(firstPerson);
            await _dbContext.SaveChangesAsync();

            firstPerson.HolidayRequests = new List<HolidayRequest>()
                    {
                        new HolidayRequest()
                        {
                            Description = "Winter Vacation",
                            CreatedAt = new DateTime(2022, 1, 1),
                            StartDate = new DateTime(2022, 1, 10),
                            EndDate = new DateTime(2022, 1, 20),
                            Status = HolidayRequestStatusEnum.Completed,
                            Type = HolidayTypeEnum.PaidLeave,
                            IsApproved = true,
                            ApprovedDate = new DateTime(2021, 12, 1),
                            ApprovedBy = approvedByFirstLeader
                        }
                    };

            _dbContext.HolidayRequests.Add(firstPerson.HolidayRequests.First());

            var secondPerson = new Person()
            {
                Id = Guid.NewGuid(),
                FirstName = "Adam",
                LastName = "Nowak",
                DateOfBirth = new DateTime(1985, 1, 1),
                Position = "Developer",
                StartDate = new DateTime(2021, 1, 1),
                IsFullTime = true,
                ContactDetails = new()
                { City = "Krakow", Street = "Zielona", Email = "[email protected]", PhoneNumber = "+48888453875", PostalCode = "30-300" },
                HolidayTimeRemain = 15,
                TeamId = _dbContext.Teams.OrderByDescending(t => t.TeamID).First().TeamID,
                Team = _dbContext.Teams.OrderByDescending(t => t.TeamID).First()
            };

            _dbContext.People.Add(secondPerson);
            await _dbContext.SaveChangesAsync();

            secondPerson.HolidayRequests = new List<HolidayRequest>()
                    {
                        new HolidayRequest()
                        {
                            Description = "Summer Vacation",
                            CreatedAt = new DateTime(2022, 1, 1),
                            StartDate = new DateTime(2022, 7, 10),
                            EndDate = new DateTime(2022, 7, 20),
                            Status = HolidayRequestStatusEnum.Completed,
                            Type = HolidayTypeEnum.PaidLeave,
                            IsApproved = true,
                            ApprovedDate = new DateTime(2021, 12, 1),
                            ApprovedBy = approvedBySecondLeader
                        }
                    };

            _dbContext.HolidayRequests.Add(secondPerson.HolidayRequests.First());
            await _dbContext.SaveChangesAsync();
        }
    }
}

Сеятель команды:

public async Task Seed()
{
    if (await _dbContext.Database.CanConnectAsync())
    {
        if (!_dbContext.Teams.Any())
        {
            var firstTeam = new Team() { Name = "Team 1", Description = "First team", IsActive = true, Department = "IT" };
            var secondTeam = new Team() { Name = "Team 2", Description = "Second team", IsActive = true, Department = "IT" };

            _dbContext.Teams.Add(firstTeam);
            _dbContext.Teams.Add(secondTeam);
            await _dbContext.SaveChangesAsync();

            firstTeam.TeamLeader = new Person()
            {
                FirstName = "Jan",
                LastName = "Kowalski",
                DateOfBirth = new DateTime(1975, 1, 1),
                Position = "Team Leader",
                StartDate = new DateTime(2019, 1, 1),
                IsFullTime = true,
                ContactDetails = new()
                { City = "Czestochowa", Street = "Miodowa", Email = "[email protected]", PhoneNumber = "+48522456675", PostalCode = "42-200" },
                HolidayTimeRemain = 5,
                TeamId = firstTeam.TeamID
            };

            secondTeam.TeamLeader = new Person()
            {
                FirstName = "Anna",
                LastName = "Kowalska",
                DateOfBirth = new DateTime(1980, 1, 1),
                Position = "Team Leader",
                StartDate = new DateTime(2020, 1, 1),
                IsFullTime = true,
                ContactDetails = new()
                { City = "Warsaw", Street = "Czerwona", Email = "[email protected]", PhoneNumber = "+48555456675", PostalCode = "00-100" },
                HolidayTimeRemain = 14,
                TeamId = secondTeam.TeamID
            };

            _dbContext.Teams.Update(firstTeam);
            _dbContext.Teams.Update(secondTeam);
            await _dbContext.SaveChangesAsync();
        }
    }
}

класс dbcontext:

public HolidayAppDbContext(DbContextOptions<HolidayAppDbContext> options) : base(options)
{
}

public DbSet<Person> People { get; set; }
public DbSet<HolidayRequest> HolidayRequests { get; set; }
public DbSet<Team> Teams { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    #region Person
    modelBuilder.Entity<Person>(eb =>
    {
        eb.Property(p => p.Id).ValueGeneratedOnAdd();
        eb.Property(p => p.FirstName).IsRequired().HasMaxLength(50);
        eb.Property(p => p.LastName).IsRequired().HasMaxLength(50);
        eb.Property(p => p.HolidayTimeRemain).IsRequired();
        eb.Property(p => p.DateOfBirth).IsRequired();
        eb.Property(p => p.Position).IsRequired().HasMaxLength(50);
        eb.Property(p => p.StartDate).IsRequired();
        eb.Property(p => p.IsFullTime).IsRequired();
        eb.HasOne(p => p.Team).WithMany(t => t.Persons).HasForeignKey(p => p.TeamId).OnDelete(DeleteBehavior.Restrict).IsRequired();
        eb.HasMany(h => h.HolidayRequests).WithOne(p => p.Person).HasForeignKey(p => p.PersonId);
        eb.OwnsOne(c => c.ContactDetails);
    });
    #endregion

    #region HolidayRequest
    modelBuilder.Entity<HolidayRequest>(eb =>
    {
        eb.Property(hr => hr.Description).IsRequired().HasMaxLength(1000);
        eb.Property(hr => hr.StartDate).IsRequired();
        eb.Property(hr => hr.EndDate).IsRequired();
        eb.Property(hr => hr.Status).IsRequired();
        eb.Property(hr => hr.Type).IsRequired();
        eb.Property(hr => hr.IsApproved).IsRequired();
        eb.Property(hr => hr.CreatedAt).IsRequired();
        eb.Property(hr => hr.UpdatedAt).IsRequired();
        eb.HasOne(hr => hr.ApprovedBy).WithMany().HasForeignKey(hr => hr.ApprovedById);
    });
    #endregion

    #region Team
    modelBuilder.Entity<Team>(eb =>
    {
        eb.Property(t => t.Name).IsRequired().HasMaxLength(50);
        eb.Property(t => t.Description).IsRequired().HasMaxLength(1000);
        eb.Property(t => t.IsActive).IsRequired();
        eb.Property(t => t.Department).IsRequired().HasMaxLength(50);
        eb.Property(t => t.CreatedDate).IsRequired();
        eb.Property(t => t.ModifiedDate);
        eb.HasOne(t => t.TeamLeader).WithOne().HasForeignKey<Person>(p => p.Id).IsRequired();
        eb.HasMany(t => t.Persons).WithOne(p => p.Team).HasForeignKey(p => p.TeamId).IsRequired();
    });
    #endregion
}

Таблица персон

Таблица команд

PS: И почему мне не хватает ссылки на лидера группы в таблице команды? Есть идеи? Я что-то пропустил?

Где и в каком порядке вы запускаете эти Seed методы и правильно ли их ожидаете?

Gert Arnold 28.05.2024 16:45

Да, я думаю, что делаю это правильно. var scope = app.Services.CreateScope(); var teamSeeder = scope.ServiceProvider.GetRequiredService<TeamSeeder>(); var personSeeder = scope.ServiceProvider.GetRequiredService<PersonSeeder>(); await teamSeeder.Seed(); await personSeeder.Seed(); Но я заметил, что идентификатор команды точно такой же, как идентификатор человека..

Rado 28.05.2024 16:51

Заполнение после builder.Build(); и перед настройкой конвейера HTTP-запросов, перенаправления https и т. д.

Rado 28.05.2024 16:56

Откуда контекст, он одинаков в обоих сидах? Выполняется ли у вас транзакция, если да, то на каком уровне изоляции?

DevilSuichiro 29.05.2024 18:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
4
64
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я не совсем знаком с беглым подходом (мы используем атрибуты модели). Но, судя по всему, вам не хватает определения столбца Id вашей команды. Что-то вроде этого: eb.Property(t => t.Id).ValueGeneratedOnAdd(); (как в случае с сущностью «Люди»)

Благодаря этому EF будет знать, что нужно получить идентификатор из базы данных после вставки. В результате firstTeam.Id и secondTeam.Id в настоящее время не установлены, поскольку вы их не установили, и EF не знает, как их получить автоматически.

Ответ принят как подходящий

Я предполагаю, что вы устанавливаете свойство TeamLeader для команд, но не устанавливаете свойство TeamLeaderId для команд.

Стандартный способ сделать это — использовать свойство TeamLeaderId Guid и свойство TeamLeader Object, которое большую часть времени является виртуальным. Стандартным способом, если вы зададите только свойство Object, ничего не произойдет, поскольку в базе данных для него нет поля.

Задайте для свойства TeamLeaderId значение идентификатора человека. Но если у вас есть автоматически сгенерированные идентификаторы, то вам нужно сначала создать людей, вызвать сохранение изменений и получить их из базы данных, после чего вы можете обновить руководителей команд.

Другие вопросы по теме