2014-11-21 7 views
5

In dieser Frage: Ef Many To Many kam eine Antwort auf, wie man manuell eine Verbindungstabelle spezifiziert. Aber ich habe eine leicht einzigartige Situation (die ich sicher nicht wirklich einzigartig bin).EF Fließende API Viele zu viele mit unterschiedlichen ID-Feldnamen

Meine zwei Tabellen haben jeweils ein Id-Feld. E.G .: [dbo].[Account].[Id] und [dbo].[Person].[Id]. Jede dieser Tabellen in meinem Code-First hat folgenden OnModelCreating:

modelBuilder.Entity<Account>.HasKey(x => x.Id); 
modelBuilder.Entity<Person>.HasKey(x => x.Id); 

Aber meine [dbo].[AccountsToPersons]... Tabelle hat Felder z.B .: [AccountId] und [PersonId]

Die AccountsToPersons Tabelle nicht von einer Klasse in Code dargestellt wird.

Ich habe offensichtlich bereits ein vorhandenes Modell, aber wir verwenden EF Code-First Fluent API anstelle der Aktualisierung des Modells aus der Datenbank.

Wie kann ich diesen Code ändern, damit er mit der Zuordnung verschiedener ID-Spaltennamen funktioniert?

public DbSet<Person> Persons { get; set; } 
public DbSet<Account> Accounts { get; set; } 
. . . 
modelBuilder.Entity<Account>() 
    .HasMany(a => a.Persons) 
    .WithMany() 
    .Map(x => 
    { 
    x.MapLeftKey("AccountId"); // <-- Account.Id to AccountsToPersons.AccountId?? 
    x.MapRightKey("PersonId"); // <-- Person.Id to AccountsToPersons.PersonId?? 
    x.ToTable("AccountsToPersons"); 
    }); 

Wenn eine grundlegende Linq To EF Abfrage läuft (from x in context.Accounts select x).ToList();, schlägt die Abfrage mit dem folgenden Fehler: "Ungültige Spaltenname 'person_id'"

Aber beim Ausführen der Abfrage (from x in context.Persons select x).ToList();, bekomme ich keinen Fehler.

Anders als Grund getippt Spalten haben meine Modelle diese ihnen hinzugefügt:

// In my Account Model, I also have this property: 
public IList<Person> Persons { get; set; } 

// In my Person Model, I also have this property: 
public IList<Account> Accounts { get; set; } // <-- in the Person model 

bitte beachten Sie, dass, obwohl meine Konten Abfrage übergibt und Feldinformationen hat, die Persons Feld immer null ist, auch wenn ich Bin mir sicher, dass es Links in meiner AccountsToPersons Tabelle gibt.

+1

Dies sieht aus wie Standard-EF-Benennung con Erfindung. Hast du das versucht? Funktioniert es?Wie sehen "Account" und "Person" aus? – Jasen

+0

@Jasen Ich dachte, es funktioniert zuerst, obwohl mein Test nur beim Erstellen des Modells war. Ich habe meinen ersten LINQ ausgeführt und es ist mit den obigen Informationen fehlgeschlagen. – Suamere

+0

Diese fließende Zuordnung sieht korrekt aus, wenn Ihre vorhandene Join-Tabelle die Spalten _AccountId_ und _PersonId_ enthält. Der Fehler liegt woanders. – Jasen

Antwort

4

Versuchen Hinzufügen p => p.Accounts auf Ihre WithMany Klausel:

modelBuilder.Entity<Account>() 
    .HasMany(a => a.Persons) 
    .WithMany(p => p.Accounts) // <-- I think this should fix it 
    .Map(x => 
    { 
    x.MapLeftKey("AccountId"); // <-- Account.Id to AccountsToPersons.AccountId?? 
    x.MapRightKey("PersonId"); // <-- Person.Id to AccountsToPersons.PersonId?? 
    x.ToTable("AccountsToPersons"); 
    }); 
+0

>. Suamere

+0

für mich funktioniert es auch ohne, komisch? – alexo

+0

@Suamere überprüfen Sie diesen Beitrag: http://StackOverflow.com/Questions/5927272/ef-Code-first-withMany – SOfanatic

2

Ich habe gerade eine Testlösung für Ihr Problem erstellt und für mich sieht es so aus, dass es funktioniert.

Eine Sache, die ich sehe, du als ich anders getan haben, ist:

public IList<Person> Persons { get; set; } // <-- in the Account model 
public IList<Account> Accounts { get; set; } // <-- in the Person model 

Versuchen Sie, in dieser Modifikation:

public DbSet<Person> Persons { get; set; } 
public DbSet<Account> Accounts { get; set; } 

Wenn dies nicht i `ll funktioniert meine gesamte Setup erstellen.

Meine Struktur sieht wie folgt aus und es funktioniert für die Abfragen, die angezeigt werden:

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

    public string Name { get; set; } 

    public IList<Account> Accounts { get; set; } 
} 

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

    public string Name { get; set; } 

    public IList<Person> Persons { get; set; } 
} 

public class ApplicationDbContext : IdentityDbContext<ApplicationUser> 
{ 
    public DbSet<Account> AccountSet { get; set; } 

    public DbSet<Person> PersonSet { get; set; } 

    public ApplicationDbContext() 
     : base("DefaultConnection") 
    { 
     this.Database.Log = (msg) => { Debug.Write(msg); }; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

     modelBuilder.Entity<Account>().HasKey(x => x.ID); 
     modelBuilder.Entity<Person>().HasKey(x => x.ID); 

     modelBuilder.Entity<Account>() 
      .HasMany(a => a.Persons) 
      .WithMany() 
      .Map(w => 
      { 
       w.MapLeftKey("AccountId"); 
       w.MapRightKey("PersonId"); 
       w.ToTable("AccountsToPersons"); 
      }); 
    } 
} 
+0

Vielen Dank, dass Sie sich die Zeit genommen haben, mein Modell zu replizieren. Wir haben jedoch ein Modellprojekt mit persistent ignorantem Modell, und das Hinzufügen von Entity Framework für das DbSet ist vom Tisch. Ich werde mir ein paar Minuten Zeit nehmen, um zu sehen, ob es überhaupt funktioniert, aber ich hoffe, dass es eine Antwort gibt, die uns nicht zwingen würde, unsere Prinzipien zu brechen, wie wir es derzeit vorbereitet haben. – Suamere

+0

Mein Entity Framework erlaubt mir nicht, DbSet zu verwenden. Bei der Suche nach dem Grund habe ich [Diese Frage] (http://stackoverflow.com/questions/14351690/ef5-code-first-error-cannot-be-inferred-from-the-usage) gefunden, dass EF Zugriff auf die ICollection benötigt die Add() - Funktionalität der Schnittstelle, um mit den Datensätzen zu arbeiten. Aber mehr Informationen von Ihnen können in Ordnung sein. Ich könnte etwas fehlen – Suamere

+0

was könnte der Grund sein, das DbSet nicht zu unterstützen? Und ja, die ICollection ist für Navigationseigenschaften, diese sind auch als teilweise markiert, weil EF eine neue Klasse auf Ihrem baut und alles überschneidet, was es als "virtuell" erscheint, in diesem Fall die ICollection Eigenschaften – alexo

0

Haben Sie versucht, etwas Ihre AccountsToPersons Mapping ändern:

modelBuilder.Entity<Account>() 
    .HasMany(a => a.Persons) 
    .WithMany(p => p.Accounts) <-- Change 
    .Map(x => 
    { 
     x.MapLeftKey("AccountId"); // <-- Account.Id to AccountsToPersons.AccountId?? 
     x.MapRightKey("PersonId"); // <-- Person.Id to AccountsToPersons.PersonId?? 
     x.ToTable("AccountsToPersons"); 
    });