Definiowanie wielu kluczy obcych dla tej samej tabeli w kodzie Entity Framework jako pierwsze

Mam dwa encje w mojej aplikacji MVC i wypełniłem bazę danych z Entity Framework 6 Code First approach. W jednostce Studenckiej znajdują się dwie legitymacje miejskie: jedna dla BirthCity, druga dla Workcity. Kiedy zdefiniuję klucze obce jak powyżej, dodatkowa kolumna jest tworzona o nazwie City_ID w tabeli Student po migracji. Id tam błąd lub jak zdefiniować te FKs? Dzięki w naprzód.

Student:

public class Student
{
    public int ID { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }

    public int BirthCityID { get; set; }

    public int LivingCityID { get; set; }


    [ForeignKey("BirthCityID")]
    public virtual City BirthCity { get; set; }

    [ForeignKey("LivingCityID")]
    public virtual City LivingCity { get; set; }
}


Miasto:

public class City
{
    public int ID { get; set; }

    public string CityName { get; set; }


    public virtual ICollection<Student> Students { get; set; }
}
Author: octavioccl, 2015-02-17

2 answers

Aby osiągnąć to, czego chcesz, musisz podać dodatkową konfigurację.Pierwsza konwencja kodu może identyfikować relacje dwukierunkowe, ale nie wtedy, gdy istnieją wielokrotne dwukierunkowe relacje między dwoma podmiotami.Możesz dodać konfigurację (używając adnotacji do danych lub Fluent API ), aby przedstawić to informacje dla konstruktora modelu. W przypadku adnotacji do danych będziesz używać adnotacji called InverseProperty. Z Fluent API, będziesz używać kombinacji Has/With metody określania poprawnych końców tych relacji.

Używanie adnotacji danych może wyglądać tak:

public class Student
{
  public int ID { get; set; }

  public string Name { get; set; }

  public string Surname { get; set; }

  public int BirthCityID { get; set; }

  public int LivingCityID { get; set; }


  [ForeignKey("BirthCityID")]
  [InverseProperty("Students")]
  public virtual City BirthCity { get; set; }

  [ForeignKey("LivingCityID")]
  public virtual City LivingCity { get; set; }
}

W ten sposób wyraźnie określasz, że chcesz powiązać właściwość nawigacyjną BirthCity z właściwością nawigacyjną Students na drugim końcu relacji.

Używanie Fluent Api może wyglądać tak:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
                                 .WithMany(m => m.Students).HasForeignKey(m=>m.BirthCityId);
     modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
                                 .WithMany().HasForeignKey(m=>m.LivingCityId);
}

Z tym ostatnim rozwiązaniem nie musisz używać żadnego attibute.

Teraz, sugestia @ChristPratt in mieć zbiór Student w klasie City dla każdego związku jest naprawdę przydatne. Jeśli to zrobisz, konfiguracje wykorzystujące adnotacje do danych mogą być takie:

public class Student
{
  public int ID { get; set; }

  public string Name { get; set; }

  public string Surname { get; set; }

  public int BirthCityID { get; set; }

  public int LivingCityID { get; set; }


  [ForeignKey("BirthCityID")]
  [InverseProperty("BirthCityStudents")]
  public virtual City BirthCity { get; set; }

  [ForeignKey("LivingCityID")]
  [InverseProperty("LivingCityStudents")]
  public virtual City LivingCity { get; set; }
}

Lub używając Fluent Api zgodnie z tą samą ideą:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Student>().HasRequired(m => m.BirthCity)
               .WithMany(m => m.BirthCityStudents).HasForeignKey(m=>m.BirthCityId);
     modelBuilder.Entity<Student>().HasRequired(m => m.LivingCity)
               .WithMany(m => m.LivingCityStudents).HasForeignKey(m=>m.LivingCityId);
}
 67
Author: octavioccl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-03 03:56:36

Sheesh. To był długi dzień. Jest naprawdę duży, rażący problem z Twoim kodem, właściwie, że zupełnie przegapiłem, gdy komentowałem.

Problem polega na tym, że używasz jednej kolekcji uczniów na City. To, co się tutaj dzieje, to fakt, że EF nie może zdecydować, do którego klucza obcego powinien mapować tę kolekcję, więc tworzy inny klucz obcy specjalnie po to, aby śledzić tę relację. W rezultacie nie masz żadnych właściwości nawigacyjnych dla kolekcji uczniów pochodzących z BirthCity i LivingCity.

W tym celu musisz przejść do konfiguracji płynnej, ponieważ nie ma sposobu, aby skonfigurować to poprawnie za pomocą tylko adnotacji danych. Będziesz również potrzebował dodatkowej kolekcji uczniów, aby móc śledzić obie relacje:

public class City
{
    ...

    public virtual ICollection<Student> BirthCityStudents { get; set; }
    public virtual ICollection<Student> LivingCityStudents { get; set; }
}

Wtedy dla Student:

public class Student
{
    ...

    public class StudentMapping : EntityTypeConfiguration<Student>
    {
        public StudentMapping()
        {
            HasRequired(m => m.BirthCity).WithMany(m => m.BirthCityStudents);
            HasRequired(m => m.LivingCity).WithMany(m => m.LivingCityStudents);
        }
    }
}

I wreszcie w Twoim kontekście:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Configurations.Add(new Student.StudentMapping());
}
 19
Author: Chris Pratt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-17 21:56:49