2014-10-21 23 views
5

Zweck erhalten: ich Schleife alle Datensätze wie:EF Liste der Datensätze in der Laufzeit von Typ

var records = db.Set<UserAccount>().ToList(); 

Dann Schleife

foreach (var record in records) 
{ 
    // do something with the record 
} 

Aber es muss nicht spezifisch in Laufzeit geben, wie Ich soll Typen durchschleifen und kenne deshalb das Beispiel "UserAccount" nicht. Nur der Type/TypeOf?

In der Unterseite dieser Beschreibung Ich habe eine Methode loopAllEntities, dass ich nicht einen Weg zur Arbeit

ich eine DbContext mit einigen Einheiten geschaffen finden.

public class MyEntities : DbContext 
{ 
    public DbSet<UserAccount> UserAccounts { get; set;} 
    public DbSet<UserRole> UserRoles { get; set; } 
    public DbSet<UserAccountRole> UserAccountRoles { get; set; } 
} 

eine Liste der Typ definiert die Ausgabe zu steuern:

public static List<Type> ModelListSorted() 
{ 
    List<Type> modelListSorted = new List<Type>(); 
    modelListSorted.Add(typeof(UserRole)); 
    modelListSorted.Add(typeof(UserAccountRole)); 
    modelListSorted.Add(typeof(UserAccount)); 
    return modelListSorted; 
} 

Das Problem ist unten, wo ich nicht einen Weg finden, damit es funktioniert :-(

public static loopAllEntities() 
{ 
    List<Type> modelListSorted = ModelHelper.ModelListSorted(); 

    foreach (Type type in modelListSorted) 
    {   
     var records = ????? // get a list of records in the current table from type. 
     foreach (var record in records) 
     { 
      // do something with the record 
     } 
    } 
} 

Antwort

1

Es sieht wie Sie es fast geschafft haben, sollten Sie in der Lage sein, so etwas wie die folgenden Funktionen ausführen:

public static void loopAllEntities(DbContext dbContext) 
    { 
     List<Type> modelListSorted = ModelHelper.ModelListSorted(); 

     foreach (Type type in modelListSorted) 
     { 
      var records = dbContext.Set(type); 
      // do something with the set here 
     } 
    } 

Dies wird Ihnen eine nicht generischen Satz erhalten, mit zu arbeiten. Es hängt davon ab, was Sie tun möchten, da es keinen Typ für dieses Set gibt, kann es ein bisschen knifflig werden, vielleicht in einen Basistyp oder eine Schnittstelle umgewandelt werden, um damit zu arbeiten?

Edit: Ich habe nicht genug Ruf zu kommentieren, aber Mayoors Lösung würden Sie bekommen, was Sie einen nicht-generischen Typen ohne Verwendung wollen und die ganze Kollektion vorne bekommen.

+0

Danke @Matt. Das war genau das, was ich brauchte :-) – pladekusken

1

ich anfangs gedacht hatte, dass man nicht nur mit einem Typ Einheit bekommen konnte, aber bei Matts Antwort suchen, Sie können. Also, diese Antwort ist wahrscheinlich nicht die beste ...

Die Grundidee ist es, eine Liste von IEnumerable<object>, wo jedes IEnumerable<object> ist eine Entität in unserem Modell zu bekommen. Der Grund, warum wir das gute alte verwenden object ist, weil wir es unterschiedliche Einheiten zurückkehren wollen, die nicht miteinander verwandt sind. Aber das ist nicht so schlimm, denn wenn Sie jedes Objekt durchlaufen, können Sie es bei Bedarf in eine bestimmte Entity umwandeln.

Zunächst werden wir eine Methode erstellen, die diese Liste zurückgibt:

private static List<IEnumerable<object>> AllEntities(MyEntities db) 
{ 
    List<IEnumerable<object>> list = new List<IEnumerable<object>>(); 
    list.Add(db.UserRole); 
    list.Add(db.UserAccountRole); 
    list.Add(db.UserAccount); 

    return list; 
} 

Wir in unserem DbContext passieren, weil es verwendet wird, wenn wir beginnen, tatsächlich durch die IEnumerables Looping, die außerhalb dieses Verfahrens auftritt. So können wir die DbContext hier nicht schaffen und dann Dispose davon.

Wir können nun diese Methode, um eine Schleife durch alle unsere Einrichtungen nutzen:

using (var db = GetMyEntities()) 
{ 
    List<IEnumerable<object>> recordsList = AllEntities(db); 
    foreach (IEnumerable<object> records in recordsList) 
    { 
     foreach (object record in records) 
     { 
      // Do something with record. 
      // If you need to access type-specific properties, 
      // do something like below 
      if (record is UserAccount) 
      { 
       UserAccount account = (UserAccount)record; 
       Console.WriteLine("User Name: " + account.UserName); 
      } 
     } 
    } 
} 

Und das ist es. In Bezug auf SQL wird für jede Iteration der äußeren foreach-Schleife so etwas wie SELECT * FROM TABLE_NAME gemacht.Dies bedeutet, dass die Daten nicht innerhalb der List<IEnumerable<object>> zwischengespeichert werden, und jedes Mal, wenn Sie AllEntities verwenden, werden neue Daten aus der Datenbank abgerufen.

+0

Danke für deine Antwort. Ich habe mich von deinem Code inspirieren lassen und ich denke, ich kann ihn in einem anderen Kontext verwenden. Die Antwort @matt gibt genau das was ich brauchte :-) – pladekusken

0

Ich weiß, dass dies eine alte Frage ist, aber die Frage spezifiziert keine EF-Version und die vorgeschlagene Antwort funktioniert nicht mehr für Entity Framework Core (DbContext hat nicht mindestens eine generische set-Methode im EF-Kern zum Zeitpunkt dieser Antwort).

Sie können immer noch eine funktionierende Erweiterungsmethode verwenden, die die Antwort von Jon Skeet auf this question verwendet. Mein Code wird zur Vereinfachung unten hinzugefügt.

public static IQueryable Set(this DbContext context, Type T) 
    { 

     // Get the generic type definition 
     MethodInfo method = typeof(DbContext).GetMethod(nameof(DbContext.Set), BindingFlags.Public | BindingFlags.Instance); 

     // Build a method with the specific type argument you're interested in 
     method = method.MakeGenericMethod(T); 

     return method.Invoke(context, null) as IQueryable; 
    } 
+0

Danke für deine Eingabe :-) Sieht sehr interessant aus! – pladekusken