[Visual Studio 2013][Entity Framework] 在 Unit Test 使用 Code Fist for Sql LocalDb

[Visual Studio 2013][Entity Framework] 在 Unit Test 使用 Code Fist for SqlLocalDb

解決 The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded 問題

在單元測試專案按照上篇的設定 http://www.dotblogs.com.tw/yc421206/archive/2014/01/21/141824.aspx 

首先,要有一個單元測試專案

在專案裡我新增了一個 Service-based Database

SNAGHTMLf53d845

 

我想要把這個檔案掛到 Microsoft SQL Server Local DB\Instances,所以連線字串如下

App.config

<connectionStrings>
  <add name="TestDb" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=IntegratedTest;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\Database1.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>

 

本以為會很順利的,但還是出錯了

image6_thumb_thumb

 

The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

 

這樣的做法在其他專案型態是可行的 Web APi/WinForm/Asp.NET MVC ,一到測試專案就不行了

上網找了一下解法,我們需要在建構子加上,以下程式碼

var instance = System.Data.Entity.SqlServer.SqlProviderServices.Instance;

參考:

http://stackoverflow.com/questions/14033193/entity-framework-provider-type-could-not-be-loaded

http://stackoverflow.com/questions/14695163/cant-find-system-data-entity-sqlserver-sqlproviderservices

 

再執行一次,又出錯,這個錯誤訊息,應該是找不到檔案的問題

image_thumb3_thumb

 

錯誤訊息如下:

An exception of type 'System.Data.SqlClient.SqlException' occurred in EntityFramework.dll but was not handled in user code

Additional information: A file activation error occurred. The physical file name '\Database1.mdf' may be incorrect. Diagnose and correct additional errors, and retry the operation.

CREATE DATABASE failed. Some file names listed could not be created. Check related errors.

SNAGHTMLf57b096

 

再動手處理一下檔案路徑的問題

AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ""));

 

參考:http://stackoverflow.com/questions/12244495/how-to-set-up-localdb-for-unit-tests-in-visual-studio-2012-and-entity-framework

再執行一次變可通過測試,完整程式碼如下

public class SQLDbContext : DbContext
{
    public SQLDbContext()
        : base("TestDb")
    {
    }

    public SQLDbContext(string connectString)
        : base(connectString)
    {
    }

    public DbSet<Identity> Identities { get; set; }

    public DbSet<Employee> Employees { get; set; }
}

public class Identity
{
    public int Id { get; set; }

    public string Account { get; set; }

    public string Domain { get; set; }
}

public class Employee
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("Id")]
    public virtual Identity Identity { get; set; }

    public string Name { get; set; }
}


在這裡重點是這兩行

var instance = System.Data.Entity.SqlServer.SqlProviderServices.Instance;
AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ""));


其他的找不到的類別不是重點,我就不貼了,對了別忘了有用到 DeploymentItem("Database1.mdf")]

[TestClass]
public class UnitTest1
{
    private IUnitOfWork _unitOfWork;
    private IRepository<Identity> _identityRepository;
    private IRepository<Employee> _employeeRepository;

    public UnitTest1()
    {
        var instance = System.Data.Entity.SqlServer.SqlProviderServices.Instance;
        AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ""));

        Database.SetInitializer(new DropCreateDatabaseAlways<SQLDbContext>());
        var dbContext = new SQLDbContext("TestDb");

        this._unitOfWork = new EFUnitOfWork(dbContext);
        this._identityRepository = new EFRepository<Identity>(this._unitOfWork as EFUnitOfWork);
        this._employeeRepository = new EFRepository<Employee>(this._unitOfWork as EFUnitOfWork);
    }
  
    [TestMethod]
    [DeploymentItem("Database1.mdf")]
    public void Insert()
    {
        var identity = new Identity() { Account = "yao", Domain = "ddd" };
        var employee = new Employee() { Identity = identity, Name = "yao" };
        this._identityRepository.Insert(identity);
        this._employeeRepository.Insert(employee);
        var expected = true;
        var actual = this._unitOfWork.Transaction();
        Assert.AreEqual(expected: expected, actual: actual);
    }
}


文章出自:http://www.dotblogs.com.tw/yc421206/archive/2014/03/28/144557.aspx

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo