2013-03-01 18 views
9

Tôi đang cố gắng xây dựng một thử nghiệm nhanh để xóa và tạo lại cơ sở dữ liệu mỗi khi nó chạy. Tôi có những điều sau đây:Lệnh CREATE DATABASE không được phép trong giao dịch đa lệnh

[TestClass] 
public class PocoTest 
{ 
    private TransactionScope _transactionScope; 
    private ProjectDataSource _dataSource; 
    private Repository _repository = new Repository(); 
    private const string _cstring = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True"; 

    [TestInitialize] 
    public virtual void TestInitialize() 
    { 
     _dataSource = new ProjectDataSource(_cstring); 
     _dataSource.Database.Delete(); 
     _dataSource.Database.CreateIfNotExists(); 
     _transactionScope = new TransactionScope(); 
    } 
    [TestMethod] 
    public void TestBasicOperations() 
    {     
     var item = _repository.AddItem(new Item(){Details = "Test Item"}); 
     // AddItem makes a call through the data context to add a set and then calls datacontext.SaveChanges() 
    } 


    [TestCleanup] 
    public void TestCleanup() 
    { 
     // rollback 
     if (_transactionScope != null) 
     { 
      _transactionScope.Dispose(); 
     } 
    } 

Tuy nhiên khi tôi chạy thử nghiệm tôi nhận được lỗi sau:

Result Message: Test method Project.Repository.UnitTests.PocoTest.TestBasicOperations threw exception: System.Data.SqlClient.SqlException: CREATE DATABASE statement not allowed within multi-statement transaction.

ProjectDataSource là ở đây:

public class ProjectDataSource : DbContext, IProjectDataSource 
{ 

    public ProjectDataSource() : base("DefaultConnection") 
    { 

    } 

    public ProjectDataSource(string connectionString) : base(connectionString) 
    { 

    } 

    public DbSet<Set> Sets { get; set; } 
} 

Repository:

public class Repository : IRepository 
{ 
    private readonly ProjectDataSource _db = new ProjectDataSource(); 
    public Item AddItem(Item item) 
     { 
      _db.Items.Add(item); 
      _db.SaveChanges(); 
      return item; 
     } 
} 

Tại sao điều này lại xảy ra?

Ngoài ra - nếu nó tạo ra bất kỳ sự khác biệt nào - lỗi không xảy ra nếu tôi nhận xét dòng AddItem trong TestMethod.

Trả lời

3

Trong trường hợp bất cứ ai khác chạy vào vấn đề này:

Trong lớp Repository của tôi, tôi có một định nghĩa về những gì thường được dán nhãn là "dbContext" - ProjectDataSource. Điều này có nghĩa là một ngữ cảnh đã được tạo ra trong lớp thử nghiệm của tôi, trong khi một ngữ cảnh khác được tạo ra trong đối tượng Repository của tôi. Gửi connectionstring đến lớp repo của tôi giải quyết vấn đề:

Trong Repository:

public class Repository : IRepository 
    { 
     private readonly ProjectDataSource _db; 

     public Repository(string connectionString) 
     { 
      _db = new ProjectDataSource(connectionString); 
     } 

     public Repository() 
     { 
      _db = new ProjectDataSource(); 
     } 

Từ thử nghiệm của tôi:

private TransactionScope _transactionScope; 
     private Repository _repository; 
     private ProjectDataSource _dataSource; 
     private const string _connectionString = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True"; 

     [TestInitialize] 
     public virtual void TestInitialize() 
     { 
      _repository = new Repository(_connectionString); 
      _dataSource = new ProjectDataSource(_connectionString); 
      _dataSource.Database.Delete(); 
      _dataSource.Database.CreateIfNotExists(); 
      _transactionScope = new TransactionScope(); 
     } 
+0

Tôi không hiểu tại sao vấn đề này lại gây ra. Bạn đang nói rằng việc tạo ra 2 thể hiện dbcontext tương đương gây ra vấn đề. có nghĩa là chỉ một dbcontext cho một db cụ thể mới có thể tồn tại trong ứng dụng? –

+0

Eran Otzap, tôi biết đó là một sự trì hoãn, nhưng đã đối mặt với vấn đề này ngày hôm nay, tôi nghĩ sẽ hữu ích khi xuất bản một câu trả lời giải thích nguyên nhân gốc rễ. Hy vọng nó giúp. –

4

Bạn cũng có thể sử dụng db.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, sqlCommand);

Xem https://stackoverflow.com/a/24344654/375114 để biết chi tiết

+0

đã giúp tôi cảm ơn bạn –

2

Để biết thông tin của bạn, lỗi này xảy ra do thiết kế và nó xảy ra bất cứ khi nào lệnh không thể giao dịch được cấp cho Microsoft SQL Server trong vòng một giao dịch ctive.

Giải pháp là, do đó, cấp rằng Cơ sở dữ liệu.CreateIfNotExists() truy cập cơ sở dữ liệu trong phạm vi giao dịch bất kỳ. Hãy nhớ rằng, SQL Profiler là bạn của bạn.

Bạn có thể nhận được khoảng updated list of commands that are not allowed to run whithin transactions. Lưu ý: Trong trường hợp người ta tự hỏi tại sao tôi cung cấp một danh sách dựa trên sản phẩm của Sybase, hãy nhớ rằng Microsoft SQL Server chia sẻ hầu hết các di truyền cơ bản của nó với động cơ Sybase '.Để đọc thêm, hãy tham khảo https://en.wikipedia.org/wiki/Microsoft_SQL_Server

Các vấn đề liên quan