1

我已經使用此GUID:http://www.c-sharpcorner.com/uploadfile/shivprasadk/wcf-faq-part-5-transactions/ 爲什麼不回滾?我不明白!WCF TransactionScope不回滾

我有一個服務和客戶端應用程序,我沒有線索這個代碼有什麼問題。 完美地做這行,並將其保存在我的數據庫後,

proxy.AddEmployee("Stav", "20"); 

下一行拋出異常becouse我沒有發送一個數字時代的參數,但成交犯規回滾的第一行這樣的信息:STAV, 20我的數據庫仍然存在!

proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception)") 

編輯1: 我添加AddEmployee實現。

客戶端:

static void Main(string[] args) 
     { 
      ServiceReference1.IJob proxy = new ServiceReference1.JobClient(); 
      using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required)) 
      { 
       try 
       { 
        proxy.AddEmployee("Stav", "20"); 
        proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception) ");//stop the running and show the Exception but keep the stav,20 in DB 
        ts.Complete(); 
       } 
       catch 
       { 
        ts.Dispose(); 
       } 
      } 
     } 

服務:

[ServiceContract] 
    public interface IJob 
    { 
     [OperationContract] 
     [TransactionFlow(TransactionFlowOption.Allowed)] 
     void AddEmployee(string Name, string Age); 
    } 
public class JobImplement:IJob 
    { 
     [OperationBehavior(TransactionScopeRequired = true)] 
     public void AddEmployee(string Name, string Age) 
     { 
string strConnection = @"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\stavalfi\Desktop\WCF2\ConsoleApplication4\WCF_DB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"; 
     SqlConnection objConnection = new SqlConnection(strConnection); 
     objConnection.Open(); 
     SqlCommand objCommand = new SqlCommand("INSERT INTO Employee (Name,Age) " + "VALUES ('" + Name + "' ,'" + Age + "')", objConnection); 
     objCommand.ExecuteNonQuery(); 
     objConnection.Close(); 
     } 
    } 
static void Main(string[] args) 
     { 
      WSHttpBinding Basic = new WSHttpBinding(); 
      Basic.TransactionFlow = true; 
      ServiceHost host = new ServiceHost(typeof(JobImplement), new Uri("http://localhost:8080")); 
      // 
      ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); 
      behavior.HttpGetEnabled = true; 
      host.Description.Behaviors.Add(behavior); 
      // 
      host.AddServiceEndpoint(typeof(IJob), new BasicHttpBinding(), "Request123"); 
      host.Open(); 
      // 
      Console.WriteLine("opened"); 
      Console.ReadLine(); 
      // 
      host.Close(); 
     } 
+0

添加如何實施AddEmployee方法?它是否真的兌現了交易? – user957902 2012-04-22 19:17:28

+0

我用這個工具更新了主題。還要別的嗎? – 2012-04-23 08:39:09

+0

你使用什麼綁定?並非所有綁定都支持事務。 – user957902 2012-04-23 12:46:22

回答

2

看起來你在你的代碼在這裏有一個可能的拼寫錯誤:

static void Main(string[] args)   
{    
    ... 
    host.AddServiceEndpoint(typeof(IJob), new BasicHttpBinding(), "Request123"); 
    ... 
} 

您要添加類型的basicHttpBinding的端點 - 不支持事務具有約束力的協議。

我在想,你其實是要做到這一點:

static void Main(string[] args)   
{    
    WSHttpBinding Basic = new WSHttpBinding(); 
    Basic.TransactionFlow = true; 
    ... 
    host.AddServiceEndpoint(typeof(IJob), Basic, "Request123"); 
    ... 
} 

這會給你一個WsHttpBinding的終點 - 有約束力的協議,不支持事務。

+0

OMG非常感謝你!我不能相信我是愚蠢的,我有2個配置文件,我忘了用BasicHttpBiding刪除。 – 2012-04-25 09:43:31

0

你應該實現自己的回滾功能。這是做這件事的基本方法。在您的服務類接口添加[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Single)]屬性。然後將這些代碼:

private SqlCommand Command { get; set; } 

[OperationContract] 
public void BeginTransaction() 
{ 
    this.Command = new SqlCommand(); 
    string strConnection = @"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\stavalfi\Desktop\WCF2\ConsoleApplication4\WCF_DB.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True"; 
    SqlConnection objConnection = new SqlConnection(strConnection); 
    objConnection.Open(); 
    this.Command.Connection = objConnection; 
} 

[OperationContract] 
public void RollBackTransaction() 
{ 
    this.Command.Transaction.Rollback(); 
} 

[OperationContract] 
public void CommitTransaction() 
{ 
    this.Command.Transaction.Commit(); 
} 

[OperationContract] 
public void CloseConnection() 
{ 
    this.Command.Connection.Close(); 
    this.Command = null; 
} 

[OperationBehavior(TransactionScopeRequired = true)] 
public void AddEmployee(string Name, string Age) 
{ 
    this.Command.CommandText = "INSERT INTO Employee (Name,Age) " + "VALUES ('" + Name + "' ,'" + Age + "')"; 
    this.Command.ExecuteNonQuery(); 
} 

然後你就可以在客戶端代碼這樣的訪問:

try 
{ 
    proxy.BeginTransaction(); 
    proxy.AddEmployee("Stav", "20"); 
    proxy.AddEmployee("Stav123", "Not a Number(-->will do Exception)"); 
    proxy.CommitTransaction(); 
} 
catch 
{ 
    proxy.RollBackTransaction(); 
} 
finally 
{ 
    proxy.CloseConnection(); 
} 

希望這有助於。

+0

在所有文章中,客戶端由transactionScope組成(如果我有多個服務 - 我正在構建一個包含一個服務的簡單示例,但在下一個示例中我將添加更多服務) - 因此TransactionScope是從客戶端管理的所有這些,所以在服務中實現我自己的事務是沒用的(如果我有更多的服務,這是沒用的 - 這是我的目標).btw,那是什麼:[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,ConcurrencyMode = ConcurrencyMode.Single)]? – 2012-04-23 11:27:30

+0

@StavAlfi [我不認爲這是可能的。](http://stackoverflow.com/a/8982167/1115937)你至少需要傳遞一個'Transaction'類型來做到這一點,但它不是可序列化的。而且您還需要在您的所有查詢中使用單個連接來獲得所需的內容。 – 2012-04-24 01:36:39

+0

我做了所有這些,那又怎麼了? – 2012-04-24 10:53:17