2015-03-02 49 views
0

我對項目有以下要求:使用EntityFramework(所有數據庫都在同一個mysql服務器上)在MySql中的多個數據庫執行預製型事務。TransactionScope與EntityFramework 6和MySql

當試圖解決的TransactionScope的問題,似乎有不同的MySQL連接字符串的問題:

「多個同時連接或與同一交易中不同的連接字符串連接目前不支持。 「

的問題已經在這裏描述的(沒有任何具體的解決方案): How do I use TransactionScope with MySql and Entity Framework? (getting Multiple simultaneous connections...are not currently supported error)

作爲一種變通方法我試過從連接字符串,如果我打開了連接,並設置數據庫,工作ommiting數據庫參數在調用.SaveChanges()方法之前(通過在繼承自DbContext的類中重載該方法)。但是爲每個選擇陳述調用相同的陳述是不可行的。

我的自定義類看起來是這樣的:

public class ContextBase : DbContext 
{ 
    public ContextBase(string connectionStringWithoutDatabase) 
     : base(connectionStringWithoutDatabase) 
    {} 

    public override int SaveChanges() 
    { 
     Database.Connection.Open(); 
     Database.Connection.ChangeDatabase("MyDatabaseName"); 
     base.SaveChanges(); 
     Database.Connection.Close(); 
    } 

    // How to handle Selects? 
} 

我的工作類單位:

public class UnitOfWork 
{ 
    private IEnumerable<DbContext> ContextList 
    { 
     get { return _contextList; } 
    } 

    private readonly IEnumerable<DbContext> _contextList; 
    public UnitOfWork(IEnumerable<DbContext> contextList) 
    { 
     _contextList = contextList; 
    } 

    public void Save() 
    { 
     var transactionScope = new TransactionScope(); 
     foreach (DbContext context in ContextList) 
     { 
      context.SaveChanges(); 
     } 
     transactionScope.Complete(); 
     transactionScope.Dispose(); 
    } 
} 

另一種可能的解決辦法是創造一個就會有兩個DbContext實例包裝 - 一個將數據庫設置爲select語句,另一個不用於非查詢操作。但這只是感覺不對。

現在我的問題(S):

  • 是否有更簡單的方式做這樣的交易?

  • 是否可以在select語句出現之前設置數據庫名稱?是否可以在構造函數中打開連接?

  • 包含兩個DbContext的包裝是否會有太多開銷?

回答

0

我們最終找到了在每次選擇前設置數據庫名稱的問題的解決方案。爲了實現這個目標,必須創建一個實現IDbCommandInterceptor的類並將其註冊到您的上下文中。在該接口的不同功能中,您可以在將SQL發送到服務器之前更改數據庫。粗略測試也顯示沒有明顯的性能下降。

1

我試着用Devart庫。這個對我有用。 下面是我運行的代碼。

不工作 - MySql.Data.MySqlClient.MySqlConnection

using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(TransactionScopeOption.Required)) 
{ 
    MySql.Data.MySqlClient.MySqlConnection connect1 = new MySql.Data.MySqlClient.MySqlConnection("Server=192.168.0.1;Database=db1;Uid=root;Pwd=root;"); 
    MySql.Data.MySqlClient.MySqlConnection connect2 = new MySql.Data.MySqlClient.MySqlConnection("Server=192.168.0.2;Database=db2;Uid=root;Pwd=root;"); 
    connect1.Open(); 
    connect2.Open(); 


    var command1 = connect1.CreateCommand(); 
    var command2 = connect2.CreateCommand(); 

    command1.CommandText = "INSERT INTO test01(`Value`) VALUES(SYSDATE());"; 
    command2.CommandText = "INSERT INTO test02(`Value`) VALUES(SYSDATE())"; 

    command2.ExecuteNonQuery(); 
    throw new Exception("bbbbbb"); 
    command1.ExecuteNonQuery(); 

    scope.Complete(); 
} 

工作 - Devart.Data.MySql.MySqlConnection

using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope(TransactionScopeOption.Required)) 
{ 
    Devart.Data.MySql.MySqlConnection connect1 = new Devart.Data.MySql.MySqlConnection("Server=192.168.0.1;Database=db1;Uid=root;Pwd=root;"); 
    Devart.Data.MySql.MySqlConnection connect2 = new Devart.Data.MySql.MySqlConnection("Server=192.168.0.2;Database=db2;Uid=root;Pwd=root;"); 
    connect1.Open(); 
    connect2.Open(); 


    var command1 = connect1.CreateCommand(); 
    var command2 = connect2.CreateCommand(); 

    command1.CommandText = "INSERT INTO test01(`Value`) VALUES(SYSDATE());"; 
    command2.CommandText = "INSERT INTO test02(`Value`) VALUES(SYSDATE())"; 

    command2.ExecuteNonQuery(); 
    throw new Exception("bbbbbb"); 
    command1.ExecuteNonQuery(); 

    scope.Complete(); 
} 
+0

謝謝你的建議的解決方案。但是atm Devart解決方案對我們來說不可行,因爲已經存在可以實現我們所需(除了所述問題之外)最多的免費解決方案。 – betelgewse 2017-05-16 07:52:45