2014-10-15 1 views
3

인터페이스를 구현하는 모든 테이블을 조회하는 방법 : 내 엔티티 클래스의 일부 인터페이스를 구현 한

public partial class Order : IReportable 
{ 
    public string TableName { get { return "Order"; } } 
} 

public partial class Client: IReportable 
{ 
public string TableName { get { return "Client"; } } 
} 


public interface IReportable 
{ 
    string TableName { get; } 
} 

그런 다음 나는 DbContext이 추가 :

public virtual DbSet<IReportable> IReportable { get; set; } 

I가 때를 여기에 표시된대로이 인터페이스를 구현하는 모든 테이블을 쿼리하십시오.

var result = from reportabletable in db.IReportable 
      where reportabletable.TableName == table_name 
      select reportabletable 

다음 예외가 발생합니다.

'Report.DataAccess.IReportable'유형이 매핑되지 않았습니다. 또는 NoMappedAttribute 데이터 주석 무시 방법을 사용하여 형식을 명시 적으로 제외하지 않았는지 확인하십시오. 형식이 이 클래스로 정의되었는지, 프리미티브가 아니거나 generic인지, 그리고 EntityObject에서 을 상속받지 않았는지 확인하십시오.

+0

많은 ORM이 해당 쿼리 유형을 제공한다면 놀랄 것입니다. –

+0

@MarcGravell 불가능하다고 말하는가? – enb081

+1

Entity Framework의 상속 전략을 확인하십시오. 나는 그것이 가능하다면 DbSet 을 가질 수는 없지만 가상 (또는 아마도 추상적 인) 속성 인 TableName을 사용하여 기본 추상 클래스로이 작업을 수행 할 수 있습니다. Btw. 여기에는 상속 전략에 대한 링크를 확인하는 TableName 속성이 있습니다. http://www.entityframeworktutorial.net/code-first/inheritance-strategy-in-code-first.aspx –

답변

5

:

이 확장 방법

public static class DbContextExtensions 
{ 
    public static IEnumerable<T> SetOf<T>(this DbContext dbContext) where T : class 
    { 
     return dbContext.GetType().Assembly.GetTypes() 
      .Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface) 
      .SelectMany(t => Enumerable.Cast<T>(dbContext.Set(t))); 
    } 
} 

를 작성하고 다음과 같이 사용 : 모든

using (var db = new dbEntities()) 
{ 
var result = from reportabletable in db.SetOf<IReportable>() 
     where reportabletable.TableName == table_name 
     select reportabletable 
} 
+1

나는 여기서 한 일을 좋아하지만 컨텍스트 테이블과 같은 어셈블리에 정의 된 인터페이스에 정말로 의지 할 수 있습니까? 'DbContext' 타입으로부터 어셈블리를 얻는 것이 더 좋지 않을까요? – Enigmativity

+1

네가 맞아, 그럴 이유가 없어. 약간의 수정으로 내 대답을 업데이트했습니다. – natenho

+0

모델이 컨텍스트와 별도의 어셈블리에 있으면이 작업도 수행되지 않습니다. AppDomain 또는 이와 유사한 항목에서 모든 어셈블리를 가져와야합니다. – GraemeMiller

2

EF는 인터페이스를 테이블에 직접 매핑하는 것을 좋아하지 않습니다. Here!

그런 다음 리포지토리 방법을 사용하고 쿼리 할 테이블의 형식을 제공하면 일반 리포지토리를 사용하여이 문제를 해결할 수 있습니다. 같은 뭔가 : myRepo.GetAll<myClient.GetType()>();

해당 인터페이스를 상속하는 클래스를 얻고 그들 모두에 대한 쿼리를 실행 :

var types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface))); 
foreach (var mytype in types) 
{ // aggregate query results } 

희망이 도움이! 더 우아한 해결책은 아마이

이 같은 뭔가를 갈 것
+0

'유형 '과 제네릭은 잘 섞이지 않습니다. 그것은 할 수 있지만 그것을 할 faff입니다 –

+0

Reflection은 Type을 인수로 전달하여 일반 메소드를 호출 할 수 있습니다. – Tengiz

1

우선 MarcGravell 코멘트는 돈에있다. 쿼리 할 테이블을 아는 것이 좋습니다. 개인적으로 나는 인터페이스를 구현하거나 사용자 정의 속성이있는 poco 유형 목록을 살펴 봅니다. 그러나 DBContext를 통해서만 이동하고자하는 경우, 여기에 "이름"에 대한 액세스를 제공하는 확장이 있습니다. 나중에 한 번에 하나씩 컨텍스트의 해당 부분에 액세스해야합니다.

다시 한 번 제네릭을 사용하여 수행 할 수 있지만 직접 제안하면됩니다.
형식 목록을 반복해야합니다. 예 :

ReportRespository : t BaseRespository : iReport로

확인 특정 유형의 조립 및 예를 들어

 /// <summary> 
    /// POCOs that have XYZ Attribute of Type and NOT abstract and not complex 
    /// </summary> 
    /// <returns></returns> 
    public static List<Type> GetBosDirDBPocoList() { 
     var result = new List<Type>(); 
     // so get all the Class from teh assembly that public non abstract and not complex 
     foreach (var t in Assembly.GetExecutingAssembly().GetTypes() 
            .Where(t => t.BaseType != null 
               && t.IsClass 
               && t.IsPublic 
               && !t.IsAbstract 
               && !t.IsComplexType() 
               && t.GetMyAttribute() != null)) { 


       result.Add(t); 
      } 
     } 
     return result; 
    } 

    public static GetMyAttribute(this Type T) { 
     var myAttr= T.GetCustomAttributes(true) 
         .Where(attribute => attribute.GetType() 
         .Name == "XYZAttr").Cast<BosDir>().FirstOrDefault(); 

     return myAttr; 
    } 

확장 속성

public static class DalExtensions { 
    // DbSet Names is the plural property name in the context 
    public static List<string> GetModelNames(this DbContext context) { 
     var propList = context.GetType().GetProperties(); 
     return GetDbSetNames(propList); 
    } 

    // DbSet Names is the plural property name in the context 
    public static List<string> GetDbSetTypeNames<T>() where T : DbContext { 
     var propList = typeof (T).GetProperties(); 
     return GetDbSetNames(propList); 
    } 

    // DBSet Types is the Generic Types POCO name used for a DBSet 
    public static List<string> GetModelTypes(this DbContext context) { 
     var propList = context.GetType().GetProperties(); 
     return GetDbSetTypes(propList); 
    } 

    // DBSet Types POCO types as IEnumerable List 
    public static IEnumerable<Type> GetDbSetPropertyList<T>() where T : DbContext { 
     return typeof (T).GetProperties().Where(p => p.PropertyType.GetTypeInfo() 
                 .Name.StartsWith("DbSet")) 
         .Select(propertyInfo => propertyInfo.PropertyType.GetGenericArguments()[0]).ToList(); 
    } 

    // DBSet Types is the Generic Types POCO name used for a DBSet 
    public static List<string> GetDbSetTypes<T>() where T : DbContext { 
     var propList = typeof (T).GetProperties(); 
     return GetDbSetTypes(propList); 
    } 


    private static List<string> GetDbSetTypes(IEnumerable<PropertyInfo> propList) { 
     var modelTypeNames = propList.Where(p => p.PropertyType.GetTypeInfo().Name.StartsWith("DbSet")) 
            .Select(p => p.PropertyType.GenericTypeArguments[0].Name) 
            .ToList(); 
     return modelTypeNames; 
    } 

    private static List<string> GetDbSetNames(IEnumerable<PropertyInfo> propList) { 
     var modelNames = propList.Where(p => p.PropertyType.GetTypeInfo().Name.StartsWith("DbSet")) 
           .Select(p => p.Name) 
           .ToList(); 

     return modelNames; 
    } 
} 
,

}

관련 문제