2014-10-21 4 views
5

Цель: Мне нужно Переберите все записи, как:EF получить список записей во время выполнения от типа

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

Тогда петля

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

Но это не тип конкретных во время выполнения, так как Я должен перебирать типы и поэтому не знаю пример «UserAccount». Только тип/типOf?

В нижней части этого описания у меня есть метод loopAllEntities, что я не могу найти способ работать

Я создал DbContext с некоторыми лицами.

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

Определяется список Тип для управления выводом:

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

Проблема ниже, где я не могу найти способ, чтобы заставить его работать :-(

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

ответ

1

Это выглядит например, вы почти находитесь, вы должны сделать что-то вроде следующего:

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

Это даст вам не общий набор для работы. Это зависит от того, что вы хотите сделать, поскольку нет такого типа для этого набора, он может стать немного сложным, может быть, брошен в базовый тип или интерфейс для работы?

Редактировать: У меня недостаточно репутации, чтобы комментировать, но решение Mayoors предоставит вам то, что вы хотите, без использования нестандартного типа и получите всю коллекцию спереди.

+0

Thank you @Matt. Это было именно то, что мне нужно :-) – pladekusken

1

Я изначально думал, что вы не можете получить сущности только с типом, но, глядя на ответ Мэтта, вы можете. Итак, этот ответ, вероятно, не самый лучший ...

Основная идея состоит в том, чтобы получить список IEnumerable<object>, где каждый IEnumerable<object> является Сущностью в нашей модели. Причина, по которой мы должны использовать простой старый object, состоит в том, что мы хотим, чтобы он возвращал разные объекты, которые не связаны друг с другом. Но это не так уж плохо, поскольку, когда вы проходите через каждый объект, вы можете отдать его определенному объекту, если вам нужно.

Во-первых, мы создадим метод, который возвращает этот список:

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

Проходим в нашем DbContext, потому что он привыкнет, когда мы на самом деле начать цикл через IEnumerables, что происходит за пределами этого метода. Итак, мы не можем создать DbContext здесь, а затем Dispose.

Теперь мы можем использовать этот метод для перебора всех наших организаций:

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

И что это. В терминах SQL он будет делать что-то вроде SELECT * FROM TABLE_NAME для каждой итерации внешнего цикла foreach.Это означает, что он не кэширует данные внутри List<IEnumerable<object>>, и каждый раз, когда вы используете AllEntities, он получает свежие данные из базы данных.

+0

Спасибо за ваш ответ. Я получил вдохновение от вашего кода, и я думаю, что могу использовать его в другом контексте. Ответ @matt дает только то, что мне нужно :-) – pladekusken

0

Я знаю, что это старый вопрос, но вопрос не указывает версию EF, и предлагаемый ответ больше не работает для ядра Entity Framework (у DbContext нет нестандартного метода набора в ядре EF, по крайней мере, на дату этого ответа).

Однако вы все еще можете использовать рабочий метод расширения, используя ответ Jon Skeet на this question. Мой код добавляется ниже для удобства.

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

Спасибо за вход :-) Выглядит очень интересно! – pladekusken

Смежные вопросы