2014-10-21 32 views
5

Cel: muszę pętli wszystkie rekordy jak:EF uzyskać listę rekordów w czasie wykonywania od typu

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

Następnie pętla

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

Ale ma nie typ specyficzny w czasie wykonywania, jak Mam zamiar przeglądać typy i dlatego nie wiem przykład "UserAccount". Tylko typ/typOff?

W dolnej części tego opisu Mam metodę loopAllEntities, że nie mogę znaleźć sposób, aby pracować

I stworzyli DbContext z kilkoma podmiotami.

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

Zdefiniowane listy Type kontrolować wyjście:

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; 
} 

Problemem jest poniżej których nie można znaleźć sposób, aby to działało :-(

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 
     } 
    } 
} 

Odpowiedz

1

Wygląda jak już prawie jesteś, powinieneś być w stanie zrobić coś takiego:

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 
     } 
    } 

Dostaniesz nietypowy zestaw do pracy. Zależy od tego, co chcesz zrobić, ponieważ nie ma typu dla tego zestawu, może być nieco skomplikowany, może być rzutowany na typ bazowy lub interfejs do pracy?

Edytuj: Nie mam wystarczającej reputacji, by komentować, ale rozwiązanie Mayoors dostarczyłoby ci tego, czego chcesz, bez użycia typowego rodzaju i otrzymasz całą kolekcję z góry.

+0

Dziękuję @Matt. To było właśnie to, czego potrzebowałem :-) – pladekusken

1

Początkowo sądziłem, że nie można uzyskać jednostek tylko typu, ale patrząc na odpowiedź Matta, można. Tak więc ta odpowiedź prawdopodobnie nie jest najlepsza ...

Podstawową ideą jest uzyskanie listy IEnumerable<object>, gdzie każdy IEnumerable<object> jest Entity w naszym modelu. Powodem, dla którego musimy używać zwykłego starego object jest to, że chcemy, aby zwracał różne jednostki, które nie są ze sobą powiązane. Nie jest to jednak takie złe, ponieważ podczas przeglądania każdego obiektu możesz go rzucić do określonej jednostki, jeśli zajdzie taka potrzeba.

Najpierw tworzymy metodę, która zwraca tę listę:

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; 
} 

mijamy w naszym DbContext ponieważ będzie przyzwyczaić gdy faktycznie zaczniemy zapętlenie poprzez IEnumerables, który występuje poza tą metodą. Tak więc nie możemy utworzyć tutaj , a następnie .

Możemy teraz wykorzystać tę metodę do pętli wszystkich naszych jednostek:

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); 
      } 
     } 
    } 
} 

I to jest to. Pod względem SQL, zrobi on coś w rodzaju SELECT * FROM TABLE_NAME dla każdej iteracji zewnętrznej pętli foreach.Oznacza to, że nie buforuje danych wewnątrz urządzenia List<IEnumerable<object>> i za każdym razem, gdy używasz AllEntities, pobiera on świeże dane z bazy danych.

+0

Dziękuję za odpowiedź. Zainspirował mnie twój kod i myślę, że mogę go użyć w innym kontekście. Odpowiedź @matt daje właśnie to, czego potrzebowałem :-) – pladekusken

0

Wiem, że to stare pytanie, ale pytanie nie określa wersji EF, a proponowana odpowiedź już nie działa dla Entity Framework Core (DbContext nie ma nietypowej metody zestawu w rdzeniu EF przynajmniej na dzień tej odpowiedzi).

Mimo to wciąż można zastosować działającą metodę rozszerzenia, korzystając z odpowiedzi Jona Skeeta na this question. Mój kod został dodany poniżej dla wygody.

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

Dziękujemy za wiadomość :-) Wygląda bardzo interesująco! – pladekusken

Powiązane problemy