2014-10-21 3 views
5

목적 기록의 목록을 다음EF는 유형에서 런타임에

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

루프

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

그러나으로, 런타임에 특정 입력하지합니다 나는 유형을 통해 반복하기 때문에 예제 "UserAccount"를 모른다. 유형/유형? 이 설명의 하단에

나는 방법에게 내가 어떤 실체가있는 DbContext를 만든

일할 수있는 방법을 찾을 수 없습니다 loopAllEntities을 있습니다.

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

@Matt. 이것은 내가 필요로했던 바로 그 것이었다 :-) – pladekusken

1

저는 처음에는 유형이있는 엔티티를 얻을 수 없다고 생각했지만 Matt의 대답을 살펴 보았습니다. 그래서,이 대답은 아마 최고의 하나가 아닙니다.

기본 아이디어는 IEnumerable<object>의 목록을 얻는 것입니다. 각 IEnumerable<object>은 우리 모델의 엔티티입니다. 일반 old 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; 
} 

우리가 실제로이 방법의 외부에서 발생하는 IEnumerables, 통해 반복 시작할 때이 익숙해 있기 때문에 우리는 우리의 DbContext 전달 :

첫째, 우리는이 목록을 반환하는 메서드를 만듭니다. 따라서 여기에 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의 관점에서, 그것은 외부 foreach 루프의 반복마다 SELECT * FROM TABLE_NAME과 같은 것을 할 것입니다.즉, List<IEnumerable<object>> 내부의 데이터를 캐싱하지 않으며, AllEntities을 사용할 때마다 데이터베이스에서 새로운 데이터를 가져옵니다.

+0

답해 주셔서 감사합니다. 나는 당신의 코드에서 영감을 얻어 다른 컨텍스트에서 사용할 수 있다고 생각합니다. @matt가주는 대답은 내가 필요한 것 :-) – pladekusken

0

이 질문은 오래된 질문이지만 EF 버전을 지정하지 않았고 제안 된 대답이 Entity Framework Core에서 더 이상 작동하지 않습니다. (DbContext는 EF 코어에서 적어도 일 반적으로 비 generic set 메서드를 갖고 있지 않습니다. 이 대답의).

아직까지 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