Вставка структуры сущностей таблицы связей "многие ко многим"

У меня есть следующие отношения: таблицы отношений

И следующие классы (только соответствующие свойства):

  1. Affair: (AffairID, Title,..., AffairsGroups)
  2. Группа: (GroupID, Name, ..., AffairsGroups)
  3. ДелаГруппы (AffairID, GroupID, Дела, Группы)

Я хочу добавить новую запись Affair в базу данных, которая также будет добавлена ​​в таблицу AffairsGroups (с известным идентификатором группы). Я пробовал это следующим образом:

private Boolean addAffairToDatabase(Affair affair)
    {
        AffairDal affairContext = new AffairDal();
        affairContext.Affairs.Add(affair);
        affairContext.SaveChanges();

        AffairsGroupDal affairsGroupContext = new AffairsGroupDal();
        affairsGroupContext.AffairsGroups.Add(new AffairsGroup{ AffairID = affair.AffairID , GroupID = user.GroupID});
        affairsGroupContext.SaveChanges();
        return true;
    }

Но я получаю следующее исключение:

SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.AffairsGroups_dbo.Affairs_AffairID". The conflict occurred in database "NuixTest.DAL.AffairsGroupDal", table "dbo.Affairs", column 'AffairID'.

Это мои контекстные классы: 1.

public class AffairDal: DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Affair>().ToTable("Affairs");
    }
    public DbSet<Affair> Affairs { get; set; }
}

2.

public class AffairsGroupDal: DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<AffairsGroup>().ToTable("AffairsGroups");
    }
    public DbSet<AffairsGroup> AffairsGroups { get; set; }
}

Что я делаю неправильно? Спасибо

1 ответ

Если твой Affairs а также Groups находятся в той же базе данных, вы должны поместить их DbSet в тот же DbContext.

Кроме того, эффективная практика заключается в том, чтобы следовать первым конвенциям Entity Framework Code. Таким образом, нет необходимости добавлять все виды атрибутов или свободный API

Ваш Affairs а также Groups иметь довольно простые отношения "многие ко многим": Group имеет ноль или более Affairsи каждый Affair может быть членом нуля или более Groups,

См. Настройка "многие ко многим".

class Affair
{
    public int Id {set; set;}

    // an Affair can be member of many Groups:
    public virtual ICollection<Group> Groups {get; set;}
    ... 
}

classs Group
{
    public int Id {set; set;}

    // a Group can have many Affairs:
    public virtual ICollection<Affair> Affairs {get; set;}
    ... 
}

class MyDbContext : DbContext
{
    public DbSet<Affair> Affairs {get; set;}
    public DbSet<Group> Groups {get; set;}
}

Entity Framework будет использовать таблицы имен дел и групп, если вы действительно хотите назвать их Affair а также Group без завершающих s, рассмотрите использование беглого API для этого.

Entity Framework автоматически определяет отношение "многие ко многим" и создает третью таблицу (AffairsGroups), если вам не нравится имя по умолчанию, снова используйте свободный API.

Приятно то, что при обычном обращении со многими ко многим вам не нужен третий стол. Выберите "Дело" и добавьте в него группу, либо выберите группу и добавьте в нее дело.

using (var myDbContext = ...)
{
    // add an affair that is not in a Group yet:
    var affair1 = myDbContext.Affairs.Add(new Affair()
    {
        Groups = new List<Group>(); // not in any group yet
    });

    // add a Group that has affair1 in it:
    var group1 = myDbContext.Groups.Add(new Group()
    {
        Affairs = new List<Affair>()
        {   // only one member: affair1:
            affair1,
        },
    });
    MyDbContext.SaveChanges();

    // as a test: retrieve affair1 again and see that it suddenly has a Group in it:
    var retrievedAffair = myDbContext.Affairs
        .Where(affair => affair.Id == affair1.Id)
        .Single();
     Debug.Assert(retrievedAffair.Groups.Any());
     Group groupOfAffair = retrievedAffair.Groups.First();
     Debug.Assert(groupOfAffair.Id == group1.Id);
}

Таким образом, не используя таблицу AffairsGroup, вы можете добавить Affair с группами или без них или группу с делами или без них. Вам не понадобится промежуточная таблица или объединение, использующее эту таблицу.

// get all Affairs that are in a Group with Name:
IEnumerable<Affair> affairs = myDbContext.Groups
    .Where(group => group.Name == Name)
    .Select(group => group.Affairs);
Другие вопросы по тегам