6

例如:-

// 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();

我正在寻找一种在运行前测试它的方法,最好是在与数据库隔离的自动化测试中。

我花了一些时间浏览 MSDN,试图找到如何实例化我自己的 QueryProvider,但我的 Google-fu 今天似乎让我失望了。

提前致谢!

4

1 回答 1

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();

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

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

Database.SetInitializer<FooContext>(null);

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

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

    Console.WriteLine(context.Foos.Where(predicate));
}

这将抛出:

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

    Console.WriteLine(context.Foos.Where(predicate));
}

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

于 2012-10-25T16:11:50.643 回答