4

我有一个 WPF 应用程序,并且在按钮单击事件中,我正在调用 WCF 服务来处理其中的事务。一笔交易完成后,我抛出异常。查看事务是否会回滚。但即使我收到错误,事务仍然完成,它不会在数据库中中止。

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

您是否在 WCF 合同中定义了交易流程?

[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]

您是否在客户端和服务器配置上都定义了事务流?

<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
         transactionFlow="true" />
</wsHttpBinding>
于 2012-09-18T10:07:03.017 回答
2
  1. You need to enable transactions in both the client and service binding by setting WSHttpBindingBase.TransactionFlow=true.

  2. You can check on the service being called if the transaction really is flowing by checking if Transaction.Current.TransactionInformation.DistributedIdentifier is non-zero. If its zero, then the flow is not working and rollback won't happed.

See the answer to How can I implement WCF Transaction support on custom class using CoreService? for more details and links.

于 2012-09-18T20:10:05.170 回答
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);
  }
}

另请注意,这些属性只是实现此目的的一种方法 - 如果需要,您也可以在配置文件中执行所有这些操作。配置文件可以更轻松地将这些设置一次性应用到多个服务。

于 2013-10-15T14:34:04.750 回答