Многие ко многим — «дочерняя / зависимая сторона не может быть определена для отношения «один к одному»»

#c# #sql #entity-framework #migration #ef-core-6.0

#c# #sql #entity-framework #миграция #ef-core-6.0

Вопрос:

Я пытаюсь достичь много-много-отношений, но я получаю:

Дочерняя / зависимая сторона не может быть определена для отношения «один к одному» между ‘Artikel.Лагер и Лагер.Artikel’. Чтобы определить дочернюю / зависимую сторону отношения, настройте свойство внешнего ключа. Если эти навигации не должны быть частью одного и того же отношения, настройте их без указания обратного. См. http://go.microsoft.com/fwlink/?LinkId=724062 для получения более подробной информации.

ER:

введите описание изображения здесь

Код:

   #region Data

    [Table("Lager")]
    public class Lager
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public string Name { get; set; } = "";
        public string Strasse { get; set; } = "";
        public string PLZ { get; set; } = "";
        public string Ort { get; set; } = "";

        public Artikel Artikel { get; set; }
    }

    [Table("LagerArtikel")]
    public class LagerArtikel
    {
        public Guid Id { get; set; } = Guid.NewGuid();

        //[ForeignKey("Lager")]
        //public Guid LagerId { get; set; }

        //[ForeignKey("Artikel")]
        //public Guid ArtikelId { get; set; }

        public int Menge { get; set; }

        public ICollection<Artikel> Artikels { get; set; }
        public ICollection<Lager> Lagers { get; set; }
    }

    [Table("Artikel")]
    public class Artikel
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public string Name { get; set; } = "";
        public decimal EinkaufspreisNettoEuro { get; set; }
        public Lager Lager { get; set; }
    }

    #endregion

    #region Context

    // => EF Core
    /*
    Add-Migration Initial -context _1_Testing.XDBContextTesting -o MigrationsXDBContextTestingMig
    add-migration -Name A3 -Project compDatMVP -context _1_Testing.XDBContextTesting
    Update-Database -context _1_Testing.XDBContextTesting 
    */

    public class XDBContextTesting : DbContext
    {
        public DbSet<Lager> Lager { get; set; }
        public DbSet<LagerArtikel> LagerArtikel { get; set; }
        public DbSet<Artikel> Artikel { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(new string(Konstanten.ConnectionString.Replace("#db#", "compDat__1__Testing")));
        }

        public XDBContextTesting() : base()
        {
        }

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

    #endregion
 

Что именно я пропустил?

Ответ №1:

Вы пропустили все «многие ко многим» 🙂

В лагере будет много артикелей, в то время как в Артикеле будет много лагеров.

 public class Lager
{
   [Key]
   public int LagerId { get; set; }
   // ...
   public virtual ICollection<LagerArtikel> LagerArtikels { get; set; } = new List<LagerArtikel>();
}

public class Artikel
{
   [Key]
   public int ArtikelId { get; set; }
    // ...
   public virtual ICollection<LagerArtikel> LagerArtikels { get; set; } = new List<LagerArtikel>();
}

public class LagerArtikel
{
    [Key]
    public int LagerArtikelId {get; set;}
    [ForeignKey("Lager")]
    public int LagerId {get; set;}
    [ForeignKey("Artikel")]
    public int ArtikelId {get; set;}

    // or just use a composite PK:
    //[Key, Column(Order=1), ForeignKey("Lager")]
    //public int LagerId {get; set;}
    //[Key, Column(Order=2), ForeignKey("Artikel")]
    //public int ArtikelId {get; set;}

    public virtual Lager Lager { get; set; }
    public virtual Artikel Artikel { get; set; }
    public int Menge { get; set; }
}
 

Поскольку связывающий объект (LagerArtikel) будет иметь дополнительные свойства, такие как Menge, вам необходимо использовать ссылку на этот объект. Если вы просто хотите, чтобы таблица LagerArtikel содержала только LagerId и ArtikelId в качестве составной PK для представления ссылки «многие ко многим», с EF6 и EF Core 5 вы могли бы отказаться от объекта LagerArtikel, и у Лагера могла быть коллекция артикелей, в то время как у Artikel есть коллекция лагеров, где EFможет управлять отношением и соответствующей таблицей без дополнительного объекта.

Подумайте об этом с точки зрения таблицы. Что бы вы поместили в таблицу LagerArtikel? У него были бы LagerId и ArtikelId, он не может хранить много лагеров и много артикелей в одной строке, вместо этого каждая строка в этой таблице связывает артикель с лагером. Многие строки будут иметь общий идентификатор ArtikelId, и многие строки будут иметь общий идентификатор LagerId.

Ответ №2:

Вам нужно заменить public Artikel Artikel { get; set; } в Lager классе, а также заменить public Lager Lager { get; set; } в Artikel классе.

Вы бы предпочли добавить public LagerArtikel LagerArtikel { get; set; } в оба класса