EF не генерирует правильный SQL SELECT WHERE при использовании динамически скомпилированного предиката - PullRequest
1 голос
/ 29 апреля 2011

Я пытаюсь создать динамический скомпилированный предикат и использовать его для запроса Entity Framework ObjectSet. Следующий код выполняется и возвращается правильный результат, но оператор SQL SELECT генерируется без предложения WHERE:

 var db = new DBHelper();

 ParameterExpression entity = Expression.Parameter(typeof(HighSchoolServicesDataAccess.Faculty), "entity");
 var filterentity = Expression.Lambda(Expression.Equal(Expression.Property(entity, "HighSchoolID"), Expression.Constant(90, typeof(int))), entity);
 Func<HighSchoolServicesDataAccess.Faculty, bool> predicate = (Func<HighSchoolServicesDataAccess.Faculty, bool>)filterentity.Compile();

 var res = db.DBContext.Faculties.Where(predicate);
 dataGridView2.DataSource = res.ToList();

Сгенерированный оператор SQL:

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[HighSchoolID] AS [HighSchoolID], 
    [Extent1].[TypeID] AS [TypeID], 
    [Extent1].[Name] AS [Name]
FROM [dbo].[Faculties] AS [Extent1]

и когда я использую явное выражение типа

var res = db.DBContext.Faculties.Where(f => f.HighSchoolID == 90);

генерируется правильный SQL.

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[HighSchoolID] AS [HighSchoolID], 
    [Extent1].[TypeID] AS [TypeID], 
    [Extent1].[Name] AS [Name]
FROM [dbo].[Faculties] AS [Extent1]
WHERE 90 = [Extent1].[HighSchoolID]

Как заставить EF создать предложение WHERE в SQL?

Ответы [ 3 ]

1 голос
/ 29 апреля 2011

Linq нуждается в выражении функции, а не скомпилированной функции. Пожалуйста, используйте рефлектор, чтобы увидеть, что генерируется компилятором для вашего выражения linq.

Дерево выражений Enire должно быть доступно для Linq where без компиляции.

 var db = new DBHelper();

 ParameterExpression entity = 
    Expression.Parameter(typeof(HighSchoolServicesDataAccess.Faculty), 
        "entity");

 Expression<Func<HighSchoolServicesDataAccess.Faculty, bool>> filterentity = 
    Expression.Lambda<Func<HighSchoolServicesDataAccess.Faculty, bool>>(
    Expression.Equal(
      Expression.Property(entity, "HighSchoolID"), 
        Expression.Constant(90, typeof(int))), entity);

 // not at all needed...
 //Func<HighSchoolServicesDataAccess.Faculty, bool> predicate =
 //   (Func<HighSchoolServicesDataAccess.Faculty, bool>)filterentity.Compile();

 var res = db.DBContext.Faculties.Where(filterentity);
 dataGridView2.DataSource = res.ToList();
1 голос
/ 29 апреля 2011

Вы создали предикат, но в конце его скомпилировали, что означает, что он больше не является выражением, и как только вы передадите его в папку, в которой вы используете linq-to-objects вместо linq-to-entity.Это означает, что все записи передаются в приложение, и фильтрация выполняется в памяти.

Попробуйте вместо этого:

var res=db.DBContext.Faculties.Where(filterentity);
dataGridView2.DataSource = res.ToList();
1 голос
/ 29 апреля 2011

Не уверен, но может ли быть так, что вы устанавливаете predicate для скомпилированного Func<...> и не сохраняете его как Expression<Func<...>>, поэтому он преобразуется в IL до того, как EF сможет его обработать?Вы пробовали, например,

var predicate = 
   (Expression<Func<HighSchoolServicesDataAccess.Faculty, bool>>)filterentity;

?

...