2017-02-23 63 views
0

我需要使用SQL Server DbContext单元测试Expression的支持。我很幸运地发现this question与亚瑟维克斯非常翔实的答案。不幸的是,我在执行过程中遇到了一些麻烦。如何防止由DbModelBuilder构建的数据库模型连接到数据库?

我已经从一个数据库(我只加了一个构造函数DbCompiledModel作为参数)创建具有自动生成DbContext一个简单的测试程序:

public partial class TestDbContext : DbContext 
{ 
    public TestDbContext() : base("name=TestDbContext") 
    { 
    } 

    public TestDbContext(DbCompiledModel model) : base(model) 
    { 
    } 

    public virtual DbSet<Foo> Foos { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
    } 
} 

的问题是,我的代码仍然连接到数据库,从它的打印数据:

var dbModelBuilder = new DbModelBuilder(); 
dbModelBuilder.Entity<Foo>().HasEntitySetName("Foos"); 
var model = dbModelBuilder.Build(new DbProviderInfo("System.Data.SqlClient", "2012")); 
var compiledModel = model.Compile(); 

Database.SetInitializer<TestDbContext>(null); 

using (var context = new TestDbContext(compiledModel)) 
{ 
    foreach (var foo in context.Foos) 
    { 
     Console.WriteLine(foo.Name); 
    } 
} 

我想,这方面我app.config文件需要数据库名从连接字符串(但是为什么,如果我不及格呢?)。我试图从这个连接字符串中删除数据库名称(“初始目录”参数),我的代码不打印Foo's。我认为,这是解决方案,但后来我尝试新的Foo实体编写和保存上下文:

context.Foos.Add(new Foo() { Name = "Bar" }); 
context.SaveChanges() 

下一次,当我执行印刷这个实体的代码。 SQL Server Management Studio在旧版本中没有看到任何新的数据库或这个实体,context.Database.Connection.Database是一个空字符串,所以看起来Entity Framework创建了一个空名称的数据库(甚至有可能?),并向它写入数据。

那么,有什么办法来防止上下文连接到数据库或创建新的?我的目标是至少运行context.Foos.Where(expression).ToList()而不连接到数据库并查看是否会有异常,因为无法将表达式转换为SQL查询。

非常感谢您的回答。

这里是我的app.config文件:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
     <section name="entityFramework" 
       type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" 
        requirePermission="false" /> 
    </configSections> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> 
    </startup> 
    <entityFramework> 
     <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> 
      <parameters> 
       <parameter value="mssqllocaldb" /> 
      </parameters> 
     </defaultConnectionFactory> 
     <providers> 
      <provider invariantName="System.Data.SqlClient" 
         type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
     </providers> 
    </entityFramework> 
    <connectionStrings> 
     <add name="TestDbContext" 
      connectionString="data source=INSPIRON;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" 
      providerName="System.Data.SqlClient" /> 
    </connectionStrings> 
</configuration> 

回答

0

因此,它看起来就像是我误会在linked answer提出的测试方法。我做了一些实验,发现通过context.Foos.Where(expression)foreach迭代并调用context.Foos.Where(expression).ToString()将使实体框架检查expression能够将其转换为SQL查询,并将创建数据库,如果它不存在。

但打完电话后:

Database.SetInitializer<TestDbContext>(null); 

context.Foos.Where(expression).ToString()仍然会检查expression并抛出异常,如果expression是不正确的,但它不会创建数据库。通过context.Foos.Where(expression)foreach迭代,即使使用正确的expression也会因为无法创建数据库而引发异常。

所以,是的,可以测试实体框架是否支持expression而不实际创建数据库或连接到现有数据库,但只能通过调用'ToString()'来返回SQL查询或抛出例外。试图迭代通过foreach的实体将无论如何连接到数据库或抛出异常,所以它不适合这种测试。这是我的错误。也许,所有这些都很明显,但不适合我,所以,我希望,我的回答可能会帮助某个人在相同的情况下。