Указание «многие ко многим», который обрабатывает две таблицы соединения (которые ранее обрабатывали многие к мужчинам) с ядром инфраструктуры сущностей - PullRequest
0 голосов
/ 11 февраля 2019

Я никогда не был в ситуации, когда у меня изначально было два решения многих ко многим, которые были разрешены.Но затем, на другом уровне, есть еще одно множество ко многим из этих таблиц соединения.Мне интересно, есть ли лучший способ для создания этого ядра структуры w / entity.Вот что я получил.Я пытаюсь выяснить, какие владельцы проекта являются частью каких продуктов проекта.

У меня есть 3 таблицы:

Проект
Продукт
Владелец

Проектможет иметь много продуктов, а проект может иметь много владельцев.Продукт может иметь много проектов, а владелец может иметь много проектов.Я решил эти два отношения «многие ко многим», выполнив следующие действия:

ProjectProduct
Два ключа: ProjectId, ProductId

ProjectOwner
Два ключа: ProjectId, OwnerId

Кроме того, ProjectProduct может иметь много ProjectOwner, а ProjectOwner может иметь много ProjectsProducts.

Я думал, что решение будет заключаться в добавлении уникального Id в оба ProjectOwnerи ProjectProduct и создайте новый объект с именем ProjectProductOwner со следующими ключами:
ProjectProductId, ProjectOwnerId

Вот как выглядит мой DBContext:

// Key Specifications
modelBuilder.Entity<ProjectProductOwner>()
    .HasKey(x => new { x.ProjectProductId, x.ProjectOwnerId });

// Project Product
modelBuilder.Entity<ProjectProduct>()
    .HasOne(x => x.Project)
    .WithMany(x => x.Products)
    .HasForeignKey(x => x.ProjectId);

modelBuilder.Entity<ProjectProduct>()
    .HasOne(x => x.Product)
    .WithMany(x => x.Projects)
    .HasForeignKey(x => x.ProductId);

// Project Owner
modelBuilder.Entity<ProjectOwner>()
    .HasOne(x => x.Project)
    .WithMany(x => x.Owners)
    .HasForeignKey(x => x.ProjectId);

modelBuilder.Entity<ProjectOwner>()
    .HasOne(x => x.Owner)
    .WithMany(x => Projects)
    .HasForeignKey(x => x.OwnerId);

// Project Product Owner
modelBuilder.Entity<ProjectProductOwner>()
    .HasOne(x => x.ProjectProduct)
    .WithMany(x => x.ProjectOwners)
    .HasForeignKey(x => x.ProjectProductId);

modelBuilder.Entity<ProjectProductOwner>()
    .HasOne(x => x.ProjectOwner)
    .WithMany(x => x.ProjectProducts)
    .HasForeignKey(x => x.ProjectOwnerId);  

IОшибкаили несколько каскадных путей.

1 Ответ

0 голосов
/ 11 февраля 2019

Вы можете "объединить" 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...