4

私はWPFアプリケーションを持っており、ボタンクリックイベントでトランザクションを処理するためにWCFサービスを呼び出しています。1 つのトランザクションが完了した後、例外をスローしています。トランザクションがロールバックするかどうかを確認します。しかし、エラーが発生してもトランザクションは完了しましたが、データベースでは中止されません。

UI ボタン​​ イベント:

private void button1_Click(object sender, RoutedEventArgs e)
{
    binding = new WSHttpBinding();
    endpoint = new EndpointAddress("http://localhost:6144/EmployeeService.svc/EmployeeService");

    ChannelFactory<IEmployeeService> cf = new ChannelFactory<IEmployeeService>(binding, endpoint);
    IEmployeeService obj = cf.CreateChannel();

    using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew))
    {
        try
        {
            obj.UpdateProductData(201, 10);
            throw new Exception("Wrong");
            obj.UpdateProductData(202, 15);
            ts.Complete();
        }
        catch (Exception ex)
        {
            ts.Dispose();                          
        }
    }
}

app.config では、既に指定されてい"transactionFlow="true"ます。

WCF サービス:

[OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)]
public bool UpdateProductData(int ProdId, int Amount)
{
    DALClass objDALProd = new DALClass();
    return objDALProd.UpdateProductData(ProdId, Amount);
}

DAL クラス:

public bool UpdateProductData(int prodID,int Amount)
{
    try
    {
        objComd.Connection = objConn;
        objConn.Open();
        objComd.CommandText = "UpdateEmployeeData";
        objComd.CommandType = CommandType.StoredProcedure;
        objParam = new SqlParameter("@ProductId", prodID);
        objComd.Parameters.Add(objParam);
        objParam = new SqlParameter("@Amount", Amount);
        objComd.Parameters.Add(objParam);

        objComd.ExecuteNonQuery();
        objConn.Close();
    }
    catch(Exception ex)
    {
        throw new FaultException("Database Error");
    }
    return true;
}

私の間違いがどこにあるか教えてください。最初のトランザクションがロールバックされない例外を発生させても、トランザクションはロールバックされません。

4

3 に答える 3

2
  1. WSHttpBindingBase.TransactionFlow =trueを設定して、クライアントとサービス バインディングの両方でトランザクションを有効にする必要があります。

  2. Transaction.Current.TransactionInformation.DistributedIdentifierがゼロでないかどうかを確認することで、トランザクションが実際に流れているかどうか、呼び出されているサービスを確認でき ます。ゼロの場合、フローは機能しておらず、ロールバックは発生しません。

CoreService を使用してカスタム クラスに WCF トランザクション サポートを実装するにはどうすればよいですか?への回答を参照してください。詳細とリンクについては。

于 2012-09-18T20:10:05.170 に答える
2

WCF コントラクトでトランザクション フローを定義しましたか?

[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]

クライアント構成とサーバー構成の両方でトランザクション フローを定義しましたか?

<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
         transactionFlow="true" />
</wsHttpBinding>
于 2012-09-18T10:07:03.017 に答える
1

クライアント側のコードは問題ないように見えますが、サーバー側では、これを機能させるために必要な属性が合計 3 つあります。

Service Interface は、操作上 [TransactionFlow] が必要です。

[ServiceContract]
public interface IService
{
  [OperationContract]
  [TransactionFlow(TransactionFlowOption.Allowed)]
  bool UpdateProductData(int ProdId, int Amount);
}

サービス クラスには、クラスに [ServiceBehavior] が必要であり、メソッドには [OperationBehavior] が必要です。

[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.ReadUncommitted)]
public class Service : IService
{
  [OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)]
  public bool UpdateProductData(int ProdId, int Amount)
  {
    DALClass objDALProd = new DALClass();
    return objDALProd.UpdateProductData(ProdId, Amount);
  }
}

また、これらの属性はこれを実現するための 1 つの方法にすぎないことに注意してください。必要に応じて、構成ファイルでこれらすべてを行うこともできます。構成ファイルを使用すると、これらの設定を一度に複数のサービスに簡単に適用できます。

于 2013-10-15T14:34:04.750 に答える