如何在WCF服务中处理事务

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);
}

DALClass:

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;
}
请让我知道我的错误在哪里。即使我首先引发异常,事务也不会回滚。

注意:您不需要 try/catch/ts.Dispose() 部分。这就是 using 块本身的作用。更糟糕的是,您在那里吞咽了所有异常。 - Christian.K
尝试将TransactionAutoComplete设置为false... - Milan Svitlica
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
2

您是否已在WCF契约中定义了事务流程?

[OperationContract]
[TransactionFlow(TransactionFlowOption.Mandatory)]
你是否在客户端和服务器配置中都定义了交易流程?
<wsHttpBinding>
<binding name="transactionalWsatHttpBinding"
         transactionFlow="true" />
</wsHttpBinding>

以下是添加到WCF合同的代码,但没有用...请让我知道是否有其他方法:[OperationBehavior(TransactionScopeRequired=true,TransactionAutoComplete=true)] public bool UpdateProductData(int ProdId, int Amount) { DALClass objDALProd = new DALClass(); return objDALProd.UpdateProductData(ProdId, Amount); } - user1661171
它看起来像是你将该属性放在了类上而不是接口上。 - Shiraz Bhaiji

2

1
你的客户端代码看起来很好,但是在服务器端,你需要获取3个属性才能使其正常工作。 服务接口需要在操作上添加[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);
  }
}
注意,这些属性只是实现此目的的一种方法 - 如果需要,您也可以在配置文件中完成所有操作。 配置文件使在一个步骤中将这些设置应用于多个服务更加容易。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,