2017-10-17 4 views
1

ich einen Tisch T1 mit vielen zu vielen Beziehung mit T2, die Verbindungstabelle ist T12 ich die entsprechenden Datensätze aus T2 erhalten möchten, in T1 die Id des Datensatzes geben, EF und LINQ, ich tue es bin wie folgt:Erhalten Datensätze von vielen zu vielen Beziehung mit ihrer Reihenfolge in der Verbindungstabelle mit EF?

var listIds = oContext.T12.Where(x => x.T1Id == id).Select(x => x.T2Id).ToList(); 
//then 
var theList = oContext.T2.In(x => x.Id, listIds).ToList(); 

Die Implementierung von In.

Ich denke nicht, dass dies der beste Weg ist, Daten aus der m-t-m-Beziehung abzufragen. sie erscheinen in SQL (die Reihenfolge, was in der Anwendung) Aber das eigentliche Problem ist, dass Datensätze aus T2 nicht in Ordnung ist:

enter image description here

aber die Reihenfolge ist T2Id: 58478, 58479, 58480, 58481

EDIT

I OrderBy verwendet listIds, um zu bekommen, aber die Liste noch nicht in der Reihenfolge, ging ich zu SSMS und machte diese Abfrage:

SELECT* FROM T2 WHERE Id IN(58481, 58478, 58479, 58480) 

und das ist das Ergebnis:

enter image description here

+0

Ist 'listIds' in Reihenfolge? Sonst benutze 'OrderBy'. – aaron

+1

Verwenden Sie keine (benutzerdefinierte) 'IEnumerable ' Erweiterung Methode mit EF 'IQueryable '. Außerdem sind keine zwei Abfragen erforderlich. Definieren und verwenden Sie Navigationseigenschaften. Und wenn die Reihenfolge von Bedeutung ist, wenden Sie 'OrderBy' an - die Reihenfolge der SQL-Abfragen ohne ORDER BY-Klausel ist nicht definiert. –

+0

Siehe meine Bearbeitung bitte –

Antwort

2

Ihr Bauchgefühl richtig ist, ist es nicht der beste Weg. Wenn Sie die Viele-zu-Viele-Beziehung in Entity Framework korrekt einrichten, müssen Sie die Joining-Tabelle T12 nicht angeben.

Siehe Configure Many To Many.

auf Ihre Klassen Angepasst:

class T1 
{ 
    public int Id {get; set;} 

    // every T1 has zero or more T2 
    public virtual ICollection<T2> T2s {get; set;} 

    // other properties 
    public int A {get; set;} 
    public string B {get; set;} 
} 

class T2 
{ 
    public int Id {get; set;} 

    // every T2 has zero or more T1 
    public virtual ICollection<T1> T1s {get; set;} 

    // other properties 
    public int C {get; set;} 
    public string D {get; set;} 
} 

public MyDbContext : DbContext 
{ 
    public DbSet<T1> T1s {get; set;} 
    public DbSet<T2> T2s {get; set;} 
} 

Das ist alles! Das Entitätsframework erkennt, dass Sie eine Viele-zu-Viele-Beziehung zwischen T1s und T2s modellieren und die zusätzliche Datenbanktabelle für Sie erstellen.

In Ihren LINQ-Abfragen benötigen Sie diese zusätzliche Tabelle nicht. Der Join wird von Linq erstellt, wenn Sie auf die Sammlungen zugreifen.

"Gib mir alle T1, wo Eigentum X == ... mit all seinen T2, wo Eigentum Y == ..."

using (var myDbContext = new MyDbContext) 
{ 
    var result = myDbContext.T1s 
     .Where(t1 => t1.X == ...) 
     .Select(t1 = new 
     { 
      // select the T1 properties you want 
      A = t1.A, 
      B = t1.B, 
      // a T1 has zero or more T2s 
      // select the T2s you want: 
      T2s = t1.T2s 
       .Where(t2 => t2.Y == ....) 
       .Select(t2 => new 
       { // Take the T2 properties you want 
        C = t2.C, 
        D = T2.D, 
       }), 
     }); 
} 

Sie auch mit T2 beginnen könnte:

var result = myDbContext.T2s 
     .Where(t2 => t2.Y == ...) 
     .Select(t1 = new 
     { 
      // select the T1 properties you want 
      C = t2.C, 
      D = t2.C, 
      // a T2 has zero or more T1s 
      // select the T1s you want: 
      T1s = t2.T1s 
       .Where(t1 => t1.Y == ....) 
       .Select(t1 => new 
       { // Take the T1 properties you want 
        A = t1.A, 
        B = T2.B, 
       }), 
     }); 

Da Sie auf die Auflistungseigenschaften im Viele-zu-Viele zugreifen, weiß Entity Framework, dass eine Verknüpfung mit der extra erstellten Viele-zu-Viele-Tabelle ausgeführt werden muss.

Das Ergebnis ähnelt einem GroupJoin.Wenn Sie es nicht gruppierten wollen, mehr wie ein echtes verbinden Sie SelectMany

var result = MyDbContext.T1s.SelectMany(t1 => t1.T2s 
    .Select(t2 => new 
    { 
     A = t1.A, 
     B = t1.B, 
     C = t2.C, 
     D = t2.D, 
    }); 

Nach meiner Erfahrung benötigen, wenn Sie Ihre one-to-many und many-to-many-Beziehungen richtig zu definieren, Sie selten zu denken brauchen in Joins. Sie greifen einfach auf die Eigenschaften zu, und das Entitätsframework erkennt automatisch, welchen Tabellen Sie beitreten müssen.

+0

Danke Harald für deine Zeit, aber ich benutze EF db-first –

Verwandte Themen