Я использую PredicateBuilder для создания многоразовых выражений в качестве возвращаемых значений объектов. Например:
public interface ISurveyEligibilityCriteria
{
Expression<Func<Client, bool>> GetEligibilityExpression();
}
Я хочу иметь автоматические тесты, которые определяют, может ли конкретное выражение трансформироваться в T-SQL с помощью Entity Framework (т. NotSupportedException
Что он не NotSupportedException
при выполнении). Я не могу найти что-либо в Интернете - возможно ли это (кажется, должно быть)?
Вы можете создать оператор LINQ, содержащий выражение, а затем проверить, можно ли его перевести без его фактического выполнения:
var connString = @"server=x;database=x";
using(var db = new MyContext(connString))
{
// ToString() shows the generated SQL string.
var sql = db.Entities.Where(generatedExpression).ToString();
Assert.IsTrue(sql.StartsWith("SELECT");
}
В Assert
вы можете протестировать все, что вы ожидаете быть частью сгенерированной строки SQL, но, конечно, если выражение не может быть переведено, тест завершится неудачно, потому что, например, NotSupportedException
.
Вы можете превратить это в удобный метод расширения:
public static class EntityFrameworkExtensions
{
public static void CompilePredicate<T>(this DbContext context, Expression<Func<T, bool>> predicate)
where T : class
{
context.Set<T>().Where(predicate).ToString();
}
}
Затем в вашем тесте:
// act
Action act = () => context.CompilePredicate(predicate);
// assert
act.ShouldNotThrow();
ToString()
. Тем не менее, это позор, что EF требует экземпляр DbContext
(возможно, это изменится в EF7)
Выполняет это очень простое решение:
using (var context = ...)
{
// The query will return null, but will be executed.
context.Clients.Where(GetEligibilityExpression())
.Where(() => false)
.SingleOrDefault();
}
В более старых версиях EF (или с использованием ObjectContext
) вы могли бы попробовать "вручную" скомпилировать запрос с помощью CompiledQuery.Compile
, но это не поддерживается DbContext
.