EF1: фильтрация производных типов класса сущностей с использованием .OfType <> путем передачи строкового значения - PullRequest
1 голос
/ 20 января 2011

У меня есть ситуация, когда я пытаюсь отфильтровать выбор LINQ, используя производный подкласс.

ctx.BaseEntity.OfType<SubClass>() - отлично работает.

Однако я бы хотел сделать это, используя вместо этого строковое значение. Я столкнулся с барьером в производительности, когда у меня много (> 20) подклассов, и выбор сущности без использования OfType просто не подходит. У меня есть общий интерфейс, который отображается из базового класса, поэтому я не знаю, какой тип класса будет возвращен во время компиляции.

Итак, что я хотел бы сделать, это:

  1. Выполнить проекцию Выбрать, где я вернуть только SubClassType из база данных
  2. Выполнить второй выбор используя это значение в качестве OfType для выберите только соответствующие сущность из базы данных (без массы созданы союзы)

        int id = 1;
        var classType = (from c in ctx.BaseClass.Include("ClassType")
                                   where c.id == id
                                   select new
                                              {
                                                  c.ClassType.TypeName
                                              }).First();
    
        BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
                        .Include("ClassType")
                        .Include("ChildEntity1")
                        .Include("ChildEntity2")
                        .Where(x => x.id== id);
    

Но, очевидно, это не сработает, потому что OfType требует Type, а не строку.

Есть идеи, как мне этого добиться?

Обновление: В качестве примечания к исходному вопросу выясняется, что в тот момент, когда вы проецируете запрос, использующий свойство навигации, - он также создает монстр SQL, поэтому я в итоге использовал хранимую процедуру для заполнения своей сущности ClassType из BaseClass. Id.

Ответы [ 2 ]

1 голос
/ 20 января 2011

Так что я просто заставил его работать с использованием eSQL, который я никогда раньше не использовал. Я разместил здесь код на случай, если он кому-нибудь поможет. У кого-нибудь еще есть более строго типизированное решение, о котором они могут подумать?

BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "])  as c")
                .Include("ClassType")
                .Include("ChildEntity1")
                .Include("ChildEntity2")
                .Where(x => x.id== id).FirstOrDefault();
0 голосов
/ 29 мая 2014

Чтобы ответить на главный вопрос о вызове OfType со строковым типом / типом времени выполнения, вы можете сделать следующее:

// Get the type, assuming the derived type is defined in the same assembly 
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
     .Assembly
     .GetType("Namespace." + derivedTypeName);

// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });

Объедините это с вашей хранимой процедурой, чтобы получить имя класса, и вы (должны?) Избежали массового объединения - у меня нет реализации таблицы для каждого типа, поэтому я не могу проверить.

...