2012-03-13 38 views
5

Tôi đang cố gắng tránh sự gia tăng MSDTC trong đơn đăng ký của mình. Tôi đang sử dụng LINQ với SQL Server Express 2008 R2, và sau này sẽ sử dụng phiên bản đầy đủ.Số giao dịch lồng nhau và/hoặc kết nối lồng nhau gây ra sự gia tăng MSDTC

Tôi đã viết một lớp trình bao bọc cơ sở dữ liệu tạo kết nối khi cần thiết và phân phối chúng càng nhanh càng tốt. Chuỗi kết nối vẫn giữ nguyên trên tất cả các kết nối.

Đây là một phiên bản rất mỏng xuống của lớp học của tôi:

public class SqlServerDatabaseWrapper { 

    public SqlServerDatabaseWrapper(string connectionString) { 
    ConnectionString = connectionString; 
    } 

    public string ConnectionString { get; private set; } 

    private static IDbConnection GetOpenConnection() { 
    var conn = new SqlConnection(ConnectionString); 
    conn.Open(); 
    return conn; 
    } 

    // there is also a second method to return a value 
    // there is PerformCommandAction for SqlCommand as well 
    public void PerformDataContextAction<TContext>(Func<IDbConnection, TContext> creator, Action<TContext> action) where TContext : DataContext { 
    PerformConnectionAction(conn => { 
     using (var context = creator(conn)) 
     action(context); 
    }); 
    } 

    // there is also a second method to return a value 
    public void PerformConnectionAction(Action<IDbConnection> action) { 
    using (IDbConnection conn = GetOpenConnection(ConnectionString)) { 
     action(conn); 
    } 
    } 
} 

Được sử dụng như sau:

var db = new SqlServerDatabaseWrapper(connectionString); 
db.PerformDataContextAction(
    conn => new SomeDataContext(conn), 
    context => { /* do something */ } 
); 

Nếu tôi đặt một khóa xung quanh nội dung của phương pháp PerformConnectionAction, vì vậy chỉ có một có thể chạy tại một thời điểm, sau đó tất cả mọi thứ hoạt động nhưng có một hình phạt hiệu suất đáng chú ý. Tuy nhiên, khi tôi xóa nó, nó sẽ leo thang.

Mã đang sử dụng trình bao bọc đang sử dụng TransactionScope và có thể lồng các TransactionScopes và/hoặc cuộc gọi đến PerformDataContextAction hoặc PerformConnectionAction (mỗi kết nối tạo một kết nối mới với cùng một chuỗi kết nối); trong pseudo-code (vì điều này có thể xảy ra trên lớp/phương pháp khác nhau):

var db = new SqlServerDatabaseWrapper(connectionString) 
using (TransactionScope tran = new TransactionScope()) { 
    db.PerformDataContextAction( 
    /* ... */, 
    context => { 
     using (TransactionScope tran2 = new TransactionScope()) { 
     db.PerformConnectionAction(conn => { /* some stuff */ }); 
     tran2.Complete(); 
     } 
    } 
    tran.Complete(); 
} 

Cũng lưu ý rằng có sử dụng các phương pháp Membership tĩnh mà có thể xảy ra tại các điểm khác nhau.

Tôi cũng nên nói thêm rằng các chuỗi kết nối như sau:

Data Source=.\SQLEXPRESS;Initial Catalog=db1;User Id=test1;Password=test1;MultipleActiveResultSets=true;Enlist=false; 

Câu hỏi đặt ra là, làm thế nào để cấu trúc lại/viết lại mã của tôi để ứng dụng của tôi có thể thực hiện tốt, không MSDTC, và không có ổ khóa giới thiệu ?

Cảm ơn

+0

Bạn đang sử dụng phiên bản SQL Server nào? – Oded

+0

SQL Express 2008 R2, sau này được đặt lên phiên bản đầy đủ – enashnash

+0

Tôi hơi bối rối khi thêm khóa ngăn chặn sự leo thang, vì 'TransactionScope' là chuỗi bị ràng buộc và khóa chỉ ảnh hưởng đến tương tác của chuỗi, nhưng không ảnh hưởng đến thứ tự của các hoạt động bên trong một luồng, trừ khi luồng của bạn giới thiệu hành vi không xác định, trong đó tôi có thể thấy các khóa thay đổi mọi thứ như thế nào. Nếu bạn vẫn còn quan tâm đến một câu trả lời, xin vui lòng cho chúng tôi biết thêm về những gì đi trên thread-khôn ngoan. –

Trả lời

1

Bạn chỉ sử dụng một kết nối với cơ sở dữ liệu bên trong phạm vi giao dịch? Tạo hai kết nối có cùng chuỗi hoặc một chuỗi kết nối khác trong phạm vi giao dịch sẽ chuyển giao giao dịch đến một giao dịch được phân phối.

Bạn có thể lưu trữ kết nối trong một biến tĩnh luồng và đóng/hủy bỏ nó khi tất cả công việc trong giao dịch được thực hiện. Sau đó, mỗi thread sẽ có kết nối riêng của nó.

Khi bạn thêm khóa vào logic của mình, có thể bạn sẽ không nhận được giao dịch phân phối vì nhóm kết nối sẽ trả lại cho bạn cùng một kết nối mỗi lần.