2012-04-06 4 views
4

Ich entwickle mit EF 4.3.1 CodeFirst. Ich habe einen Flughafen Tabelle wie folgt:Viele zu vielen (Join-Tabelle) Beziehung mit der gleichen Entität mit CodeFirst oder fließend API?

public class Airport 
    { 
     [Key] 
     public int ID { get; set; } 
     public string Name{ get; set; } 
    } 

Was ich brauche, ist eine Strecke Tisch mit 2 FKs vom gleichen Flughafen Tisch wie:

public class Route 
    { 
     public int DepartureAirportID { get; set; } 
     public int DestinationAirportID { get; set; } 
     public virtual Airport DestinationAirport { get; set; } 
     public virtual Airport DepartureAirport { get; set; } 
    } 

Wie kann dies erreicht werden?

Antwort

3

Dies sollte das tun, was Sie ... benötigen

public class Airport 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Route> DepartureRoutes { get; set; } 
    public virtual ICollection<Route> DestinationRoutes { get; set; } 
} 
public class Route 
{ 
    public int DepartureAirportID { get; set; } 
    public int DestinationAirportID { get; set; } 
    public Airport DestinationAirport { get; set; } 
    public Airport DepartureAirport { get; set; } 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Route>() 
     .HasKey(i => new { i.DepartureAirportID, i.DestinationAirportID}); 

    modelBuilder.Entity<Route>() 
     .HasRequired(i => i.DepartureAirport) 
     .WithMany(u => u.DepartureRoutes) 
     .HasForeignKey(i => i.DepartureAirportID) 
     .WillCascadeOnDelete(false); 

    modelBuilder.Entity<Route>() 
     .HasRequired(i => i.DestinationAirport) 
     .WithMany(u => u.DestinationRoutes) 
     .HasForeignKey(i => i.DestinationAirportID) 
     .WillCascadeOnDelete(false); 
} 

... das schafft Tabellen wie ...

CREATE TABLE [Airports] (
    [ID] [int] NOT NULL IDENTITY, 
    [Name] [nvarchar](4000), 
    CONSTRAINT [PK_Airports] PRIMARY KEY ([ID]) 
) 
CREATE TABLE [Routes] (
    [DepartureAirportID] [int] NOT NULL, 
    [DestinationAirportID] [int] NOT NULL, 
    CONSTRAINT [PK_Routes] PRIMARY KEY ([DepartureAirportID], [DestinationAirportID]) 
) 
CREATE INDEX [IX_DestinationAirportID] ON [Routes]([DestinationAirportID]) 
CREATE INDEX [IX_DepartureAirportID] ON [Routes]([DepartureAirportID]) 
ALTER TABLE [Routes] ADD CONSTRAINT [FK_Routes_Airports_DestinationAirportID] FOREIGN KEY ([DestinationAirportID]) REFERENCES [Airports] ([ID]) 
ALTER TABLE [Routes] ADD CONSTRAINT [FK_Routes_Airports_DepartureAirportID] FOREIGN KEY ([DepartureAirportID]) REFERENCES [Airports] ([ID]) 

... und Sie können es wie so verwenden ...

using (var db = new MyDbContext()) 
{ 
    foreach (var routeid in Enumerable.Range(1, 100)) 
    { 
     var departure = new Airport { Name = "departure" + routeid }; 
     db.Airports.Add(departure); 
     var destination = new Airport { Name = "destination" + routeid }; 
     db.Airports.Add(destination); 

     var route = new Route{ DepartureAirport = departure, DestinationAirport = destination }; 
     db.Routes.Add(route); 
    } 

    int recordsAffected = db.SaveChanges(); 

    foreach (var route in db.Routes) 
    { 
     Console.WriteLine("{0}, {1}, {2}, {3}", route.DepartureAirportID, route.DestinationAirportID, route.DepartureAirport.Name, route.DestinationAirport.Name); 
    } 
} 

... hoffe das hilft. Hinweis: Verwenden Sie nicht virtual auf erforderlichen Eigenschaften (wie diese sind Indizes - und für diese Art der Zuordnung wird nur so funktionieren, werden Sie einige Fehler, denke ich).
Auch ich füge immer die entgegengesetzten Beziehungen hinzu, aber Sie können WithMany() leer verwenden, sollte auch funktionieren.

+0

Danke NSGaga! Ich bin neu bei MVC. Ich benutze EF 4.3.1. Können Sie mir aktuelle und effiziente Quellen vorschlagen, um mehr über CodeFirst Fluent API und Beziehungen zu erfahren? – oislek

+0

Geben Sie ihr eine 'Entity Framework Walkthrough' auf Google (für das vergangene Jahr) - und das sollte Ihnen viel geben. Folgen Sie [MS ADO.NET Foren] (http://blogs.msdn.com/b/adonet/), da die meisten Dinge dort gefragt werden (obwohl die Antworten langsamer sind). Btw bitte 'upvote' auch, wenn Sie das nützlich finden! – NSGaga

+0

Nsaga Ich würde es tun, sogar es ist tatsächlich "ist" nicht :) aber die Antwort oben und Ihre Mühe würde es sehr verdienen. Aber ich konnte nicht coz ich bekam eine Warnung als "Vote Up erfordert 15 Ruf". Sorry Kumpel :( – oislek

0

Sie sollten eine zusätzliche selbstbezogene Eigenschaft Ihrer Klasse Flughafen hinzu:

public class Airport 
{ 
    public int ID { get; set; } 
    public string Name{ get; set; } 
    public virtual ICollection<Airport> AirportRoutes { get; set; } 
} 

Und außer Kraft setzen OnModelCreating Methode mit dem nächsten Fluent API-Code:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Entity<Airport>().HasMany(x => x.AirportRoutes).WithMany().Map(
      x => 
       { 
        x.MapLeftKey("DepartureId");  // left key name 
        x.MapRightKey("DestinationId"); // right key name 
        x.ToTable("Routes");    // table name 
       }); 
} 

Hope this Ihnen hilft.

+0

Danke @Beebik. Empfehlen Sie dies als eine Alternative zu der ALTER TABLE-Lösung, die ich in meinen Kommentaren zu NSGaga erwähnt habe? – oislek

Verwandte Themen