2017-02-23 52 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的實體將無論如何連接到數據庫或拋出異常,所以它不適合這種測試。這是我的錯誤。也許,所有這些都很明顯,但不適合我,所以,我希望,我的回答可能會幫助某個人在相同的情況下。