Вы можете "объединить" ProjectProduct
с ProjectProductOwner
в одну таблицу.Поскольку вы сначала добавляете Owners
к Project
, то вы добавляете один или несколько Products
для каждого Owner
в Project
. Я не вижу необходимости в третьем объекте «многие ко многим», поэтомунемного упростить его:)
Примечание: я даже не беспокоился об ошибке, потому что, как вы сказали, и я согласен, чаще всего эти ошибки появляются, когда ваша модель не верна.
Owner
public class Owner
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ProjectOwner> ProjectOwners { get; set; }
public ICollection<ProjectProductOwner> ProjectProductOwners { get; set; }
}
Product
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ProjectProductOwner> ProjectProductOwners { get; set; }
}
Project and many-to-many tables
public class Project
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ProjectOwner> ProjectOwners { get; set; }
public ICollection<ProjectProductOwner> ProjectProductOwners { get; set; }
public Project()
{
ProjectOwners = new List<ProjectOwner>();
ProjectProductOwners = new List<ProjectProductOwner>();
}
}
public class ProjectOwner
{
public int OwnerId { get; set; }
public Owner Owner { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
public class ProjectProductOwner
{
public int ProductId { get; set; }
public Product Product { get; set; }
public int OwnerId { get; set; }
public Owner Owner { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
DbContext
конфигурация
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure Owners in a Project
modelBuilder.Entity<ProjectOwner>()
.HasKey(p => new { p.ProjectId, p.OwnerId });
modelBuilder.Entity<ProjectOwner>()
.HasOne(bc => bc.Project)
.WithMany(b => b.ProjectOwners)
.HasForeignKey(bc => bc.ProjectId);
modelBuilder.Entity<ProjectOwner>()
.HasOne(bc => bc.Owner)
.WithMany(c => c.ProjectOwners)
.HasForeignKey(bc => bc.OwnerId);
// Configure Products for each owner in a Project
modelBuilder.Entity<ProjectProductOwner>()
.HasKey(p => new { p.ProjectId, p.ProductId, p.OwnerId });
modelBuilder.Entity<ProjectProductOwner>()
.HasOne(bc => bc.Project)
.WithMany(b => b.ProjectProductOwners)
.HasForeignKey(bc => bc.ProjectId);
modelBuilder.Entity<ProjectProductOwner>()
.HasOne(bc => bc.Product)
.WithMany(c => c.ProjectProductOwners)
.HasForeignKey(bc => bc.ProductId);
modelBuilder.Entity<ProjectProductOwner>()
.HasOne(bc => bc.Owner)
.WithMany(c => c.ProjectProductOwners)
.HasForeignKey(bc => bc.OwnerId);
}
Наконец, вы можете добавить новые проекты и запросить их примерно так:
using (var db = new ProjectContext())
{
var project = new Project();
project.Name = "My project";
// assumes there's 3 owners and 2 products already inserted in the DB
// Add the 3 owners to the project
project.ProjectOwners.Add(new ProjectOwner { OwnerId = 1});
project.ProjectOwners.Add(new ProjectOwner { OwnerId = 2});
project.ProjectOwners.Add(new ProjectOwner { OwnerId = 3});
// Add Product 1 to Owner 1 and 2
project.ProjectProductOwners.Add(new ProjectProductOwner { ProductId = 1, OwnerId = 1 });
project.ProjectProductOwners.Add(new ProjectProductOwner { ProductId = 1, OwnerId = 2 });
// Add Product 2 to Owner 1 and 3
project.ProjectProductOwners.Add(new ProjectProductOwner { ProductId = 2, OwnerId = 1 });
project.ProjectProductOwners.Add(new ProjectProductOwner { ProductId = 2, OwnerId = 3 });
db.Add(project);
db.SaveChanges();
var projects = db.Project
.Include(p => p.ProjectOwners)
.ThenInclude(p => p.Owner)
.Include(p => p.ProjectProductOwners)
.ThenInclude(p => p.Product)
.FirstOrDefault();
}