Найти динамический DbSet в DbContext динамически

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

Вопрос

Я знаю, что этот вопрос уже задан, но я не мог найти ответа, который меня удовлетворил. То, что я пытаюсь сделать, - это получить конкретный 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 он будет. Тогда где-то еще в той же сборке я использую ее так:

// MyDbContext MyDbContextInstance..
var model = MyDbContextInstance.GetByName_SwitchTest("A");
var record1 = model.FirstOrDefault(); // It crashes here with RunTimeBinderException

В этой точке model содержит экземпляр типа InternalDbSet<ModelA> . Оттуда, любое использование, которое я использую с объектом model я получаю RunTimeBinderException: «Microsoft.Data.Entity.Internal.InternalDbSet» не содержит определения для «FirstOrDefault»,

Расследуя в Интернете, я нашел сообщение в блоге, объясняющее, что (dixit его блог):

причиной отказа вызова FirstOrDefault () является то, что информация о типе модели недоступна во время выполнения. Причина, по которой она недоступна, заключается в том, что анонимные типы не являются общедоступными. Когда метод возвращает экземпляр этого анонимного типа, он возвращает System.Object, который ссылается на экземпляр анонимного типа - тип, информация которого недоступна основной программе.

И затем он указывает, что решение:

Решение на самом деле довольно простое. Все, что нам нужно сделать, это открыть AssemplyInfo.cs проекта ClassLibrary1 и добавить к нему следующую строку: [assembly:InternalsVisibleTo("assembly-name")]

Я попробовал это решение на своем коде, но он не работает. Для информации у меня есть решение asp.net 5 с двумя сборками, работающими на dnx dotnet46. Приложение и DLL, содержащая все мои модели и DbContext. Однако все связанные звонки, которые я делаю, расположены на dll.

Имеет ли это решение возможность работать? Я что-то упускаю ? Любые указатели будут очень признательны?

заранее спасибо

[РЕДАКТИРОВАТЬ]

Я попытался вернуть IQueryable<dynamic> вместо dynamic и я мог бы сделать базовую model.FirstOrDefault(); запроса. model.FirstOrDefault(); но прежде всего я хотел бы также фильтровать поле:

var record = model.FirstOrDefault(item => item.MyProperty == true);

Популярные ответы

Итак, как я это сделал, когда я не знал о <T> во время компиляции.

Сначала нужно получить тип, поскольку метод DbContext.Set возвращает не общий экземпляр DbSet для доступа к объектам данного типа в контексте и в базовом хранилище.

public virtual DbSet Set(Type entityType)

Обратите внимание, что здесь аргумент - это тип объекта, для которого должен быть возвращен набор. И для данного типа объекта задано возвращаемое значение.

var type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == <Pass your table name>);

теперь, когда у меня есть этот тип

if(type != null)
{
DbSet context = context.Set(type);
}

Или один лайнер будет

DbSet mySet = context.Set(Type.GetType("<Your Entity Name>"));


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему