是否可以测试给定的表达式是否可以转换为SQL*而无需*连接到SQL数据库?

Iai*_*way 6 c# entity-framework

例如:-

// This one will be converted to SQL no problem
Expression<Func<Foo, bool>> predicate = x => x.Name = "Foo";

// This one will throw a NotSupportedException because the QueryProvider
// doesn't support reference comparisons
Expression<Func<Foo, bool>> predicate = x => x == someOtherFoo;

// This one doesn't work because the query provider can't
// handle IsAwesome()
Expression<Func<Foo, bool>> predicate = x => x.IsAwesome();
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种在运行之前测试它的方法,理想情况是在与数据库隔离的自动化测试中.

我花了一些时间在MSDN上搜索试图找到如何实例化我自己的QueryProvider,但我的Google-fu似乎今天失败了.

提前致谢!

Art*_*ers 4

您需要一个模型来执行此操作,但不需要数据库。您可以将模型创建为 EDMX,但使用 Code First 可能更容易。为了确保创建或使用 Code First 模型不需要数据库连接,您需要提供 Code First 通常从数据库获取的一些信息。这篇文章http://blog.oneunicorn.com/2012/04/21/code-first-building-blocks/展示了如何使用 DbModelBuilder 来执行此操作以及如何从模型创建 DbContext。您最终会得到如下代码:

var modelBuilder = new DbModelBuilder();
modelBuilder.Entity<Foo>();
var model = modelBuilder.Build(
                new DbProviderInfo("System.Data.SqlClient", "2008")).Compile();
Run Code Online (Sandbox Code Playgroud)

您可能希望缓存模型对象,而不是为每个不同的测试再次创建它。

您还应该禁用数据库初始值设定项以防止 DbContext 尝试连接到数据库。例如,在使用上下文之前进行如下调用:

Database.SetInitializer<FooContext>(null);
Run Code Online (Sandbox Code Playgroud)

现在您可以在任何查询上使用 ToString 来查看它将生成什么 SQL。如果 LINQ 无法处理该表达式,则会出现异常。例如,这将打印查询:

using (var context = new FooContext(model))
{
    Expression<Func<Foo, bool>> predicate = x => x.Name == "Foo";

    Console.WriteLine(context.Foos.Where(predicate));
}
Run Code Online (Sandbox Code Playgroud)

这会抛出:

using (var context = new FooContext(model))
{
    var someOtherFoo = new Foo();
    Expression<Func<Foo, bool>> predicate = x => x == someOtherFoo;

    Console.WriteLine(context.Foos.Where(predicate));
}
Run Code Online (Sandbox Code Playgroud)

显然,如果您正在编写测试,您将不仅仅是打印到控制台,而是执行某种断言/检查。