Не могу понять как связать сущности в EntityFramework
подскажите как связать эти две сущности, что бы в бд создавались 2 связанные таблицы. Читаю статью на метаните и не могу понять. Появляется ошибка InvalidOperationException: The seed entity for entity type 'Employee' cannot be added because no value was provided for the required property 'DepartmentId'.
public class Department
{
[Key]
public int DepartmentId { get; set; }
public string Name { get; set; } = null!;
}
public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string FirstName { get; set; } = null!;
public string LastName { get; set; } = null!;
public string DateOfBirth { get; set; } = null!;
public string Adress { get; set; } = null!;
public int DepartmentId { get; set; }
[ForeignKey("DepartmentId")]
public Department Department { get; set; } = null!;
public string? Description { get; set; }
}
public class AppDbContext : DbContext, IDbContext
{
public DbSet<Employee> Employees { get; set; } = null!;
public DbSet<Department> Departments { get; set; } = null!;
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().HasData(
new Department { DepartmentId = 1, Name = "Dev" },
new Department { DepartmentId = 2, Name = "Marketing" },
new Department { DepartmentId = 3, Name = "Art" });
modelBuilder.Entity<Employee>().HasData(
new Employee { Id = 1, FirstName = "Максим", LastName = "Максимов",Department = new(1,"DepName1"), DateOfBirth = "22.11.1990", Adress = "Novosibirsk", Description = "" },
new Employee { Id = 2, FirstName = "Иван", LastName = "Иванов", Department = new(2, "DepName2"), DateOfBirth = "12.02.1996", Adress = "SPB", Description = ""},
new Employee { Id = 3, FirstName = "Дмитрий", LastName = "Дмитриев", Department = new(3, "DepName3"), DateOfBirth = "10.06.1998",Adress = "MSK", Description = ""});
}
}
Ответы (2 шт):
Связь образуется благодаря вызову "Has" на одной из сторон отношения. В вашем случе нужно добавить дополнительное свойство к Департаменту
public List<Employee> Employees { get; set; }
а затем объявить связь "1-ко-многим" между этими сущностями, добавив следующий вызов в конфигурацию Департамента:
modelBuilder.Entity<Employee>()
.HasOne(c => c.Department)
.WithMany(u => u.Employees)
.HasForeignKey(k => k.DepartmentId)
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
Давайте на простых примерах.
Классы сущностей:
public class Department
{
public int Id { get; set; }
public string Name { get; set; } = null!;
public List<Employee> Employees { get; set; } = null!;
}
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; } = null!;
public int DepartmentId { get; set; }
public Department Department { get; set; } = null!;
}
Я удалил все остальные свойства, чтобы они не мешались.
Атрибут [Key] можно не указывать, если свойство соответствует соглашениям: имеет название Id или <Entity>Id (EmployeeId, DepartmentId). Но если хотите, можете его оставить.
Атрибут [ForeignKey(...)] тоже можно не указывать, если имя соответствует принятым соглашениям.
Для образования связи один-ко-многим (one-to-many) у нас должна быть коллекция (например, List<Employee>) с одной стороны и одиночное свойство соответствующего типа (Department) с другой стороны. Entity Framework сам создаст необходимые связи.
Теперь перейдём к заполнению данных.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Department>().HasData(
new Department { Id = 1, Name = "Dev" },
new Department { Id = 2, Name = "Marketing" },
new Department { Id = 3, Name = "Art" }
);
modelBuilder.Entity<Employee>().HasData(
new Employee { Id = 11, DepartmentId = 1, FirstName = "Максим" },
new Employee { Id = 12, DepartmentId = 2, FirstName = "Иван" },
new Employee { Id = 13, DepartmentId = 3, FirstName = "Дмитрий" }
);
}
Этот код работает, при условии, что айдишники заданы вручную.
Обратите внимание, что номера 1, 2 и 3 совпадают.
Причём указать их нужно обязательно, т. к. свойства DepartmentId и Department сделаны non-nullable.
Если их сделать nullable:
public int? DepartmentId { get; set; }
public Department? Department { get; set; }
то в методе HasData можно будет опустить задание DepartmentId. Данные будут вставлены, но связи между ними не будет.