동적으로 DbContext에서 일반 DbSet 찾기

.net asp.net-mvc-5 c# entity-framework-core

문제

나는이 질문이 이미 요구되었음을 알고 있지만 나는 나를 만족시키는 답을 찾을 수 없었다. 내가 뭘 DbSet<T> 유형의 이름을 기반으로 특정 DbSet<T> 를 검색하는 것입니다.

나는 다음과 같은 것을 가지고있다.

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyDllAssemblyName")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyCallingAssemblyName")]

class MyDbContext : DbContext {

    public DbSet<ModelA> A { get; set; }
    public DbSet<ModelB> B { get; set; }

    public dynamic GetByName_SwitchTest(string name) {
        switch (name) {
            case "A": return A;
            case "B": return B;
        }
    }

    public dynamic GetByName_ReflectionTest(string fullname)
    {
        Type targetType = Type.GetType(fullname);
        var model = GetType()
            .GetRuntimeProperties()
            .Where(o => 
                o.PropertyType.IsGenericType &&
                o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                o.PropertyType.GenericTypeArguments.Contains(targetType))
            .FirstOrDefault();
        if (null != model)
            return model.GetValue(this);
        return null;
    }
}

간단한 전환이나 반사를 통해 유형 자체를 가져 오는 데 문제가 없습니다. 그러나 DbSet 타입이 무엇인지 알지 못하기 때문에 유형을 동적으로 반환해야합니다. 그런 다음 동일한 어셈블리의 다른 어딘가에서이 방법으로 사용합니다.

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyDllAssemblyName")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyCallingAssemblyName")]

class MyDbContext : DbContext {

    public DbSet<ModelA> A { get; set; }
    public DbSet<ModelB> B { get; set; }

    public dynamic GetByName_SwitchTest(string name) {
        switch (name) {
            case "A": return A;
            case "B": return B;
        }
    }

    public dynamic GetByName_ReflectionTest(string fullname)
    {
        Type targetType = Type.GetType(fullname);
        var model = GetType()
            .GetRuntimeProperties()
            .Where(o => 
                o.PropertyType.IsGenericType &&
                o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                o.PropertyType.GenericTypeArguments.Contains(targetType))
            .FirstOrDefault();
        if (null != model)
            return model.GetValue(this);
        return null;
    }
}

이 시점에서 modelInternalDbSet<ModelA> 유형의 인스턴스를 포함합니다. 거기에서, 내가 RunTimeBinderException 얻을 model 개체와 함께 할 : 'Microsoft.Data.Entity.Internal.InternalDbSet'에 대한 정의가 포함되어 있지 않습니다 'FirstOrDefault'

웹에서 조사한 결과, 블로그 게시물에 다음과 같은 내용이 설명되어 있습니다.

FirstOrDefault ()에 대한 호출이 실패하는 이유는 런타임에 모델의 유형 정보를 사용할 수 없기 때문입니다. 익명 형식이 공개되지 않기 때문에 사용할 수없는 이유가 있습니다. 메서드가 익명 형식의 인스턴스를 반환하면 익명 형식의 인스턴스를 참조하는 System.Object를 반환합니다.이 형식의 정보는 주 프로그램에서 사용할 수 없습니다.

그리고 그는 그 해결책을 지적합니다 :

해결책은 실제로 매우 간단합니다. 우리가해야 할 일은 ClassLibrary1 프로젝트의 AssemplyInfo.cs를 열고 다음 줄을 추가하는 것입니다 : [assembly:InternalsVisibleTo("assembly-name")]

내 코드에서이 솔루션을 시도했지만 작동하지 않습니다. 정보를 위해 나는 dnx dotnet46에서 실행되는 두 개의 어셈블리로 구성된 asp.net 5 솔루션을 가지고 있습니다. 내 모든 모델과 DbContext를 포함하는 응용 프로그램과 dll 모든 관련 전화는 내가 dll에 위치하고 있습니다.

이 솔루션이 작동 할 기회가 있습니까? 내가 놓친 게 있니? 모든 포인터가 크게 감사하겠습니다?

미리 감사드립니다.

[편집하다]

내가 돌아 시도 IQueryable<dynamic> 보다는 dynamic 나는 기본적인 쿼리 할 수 model.FirstOrDefault(); 하지만 무엇보다 필드에서 필터링 할 수 있기를 원합니다.

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyDllAssemblyName")]
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyCallingAssemblyName")]

class MyDbContext : DbContext {

    public DbSet<ModelA> A { get; set; }
    public DbSet<ModelB> B { get; set; }

    public dynamic GetByName_SwitchTest(string name) {
        switch (name) {
            case "A": return A;
            case "B": return B;
        }
    }

    public dynamic GetByName_ReflectionTest(string fullname)
    {
        Type targetType = Type.GetType(fullname);
        var model = GetType()
            .GetRuntimeProperties()
            .Where(o => 
                o.PropertyType.IsGenericType &&
                o.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) &&
                o.PropertyType.GenericTypeArguments.Contains(targetType))
            .FirstOrDefault();
        if (null != model)
            return model.GetValue(this);
        return null;
    }
}

인기 답변

컴파일하는 동안 <T> 모르는 경우 어떻게했을까요?

먼저 DbContext.Set 메서드가 컨텍스트 및 기본 저장소에서 지정된 형식의 엔터티에 액세스하기 위해 비 제네시 DbSet 인스턴스를 반환하도록 형식을 가져와야 합니다.

public virtual DbSet Set(Type entityType)

여기서 인수는 집합이 반환되어야하는 엔터티의 형식입니다. 주어진 엔터티 형식에 대해 설정된 값은 반환 값입니다.

public virtual DbSet Set(Type entityType)

이제는이 유형을 갖게되었습니다.

public virtual DbSet Set(Type entityType)

또는 하나의 라이너가 될 것입니다.

public virtual DbSet Set(Type entityType)



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.