Exception "Transaction canceled" when creating a new TransactionScope ()

This is my first WCF both client and server. SQL Server 2008.

I am forced to use TransactionScope from my Windows Forms Application which is working as a client against WCF service. I haven't used this type of transaction before, usually using connection.BeginTransaction (), which I like because it's easier to keep track of what's going on.

I call a function (I hope these are nesting transactions), but one of my calls to create a new TransactionScope instance crashes with a "Transaction excluded" exception. The inner exception is null. I am assuming the transaction came back before this, but I have no idea how to track if an ambient transaction was done and what the status was.

example client (not real code. I've verified that all funcs use scope.Commit ()) Any help on how to track down the issue please?

(Often I get error messages that the MSDTC service needs to be started, but I don’t understand why it is used when distributing with a single database / wcf service)

void Function1(AMessageObj m)
{
  using (var client = GetOpenWebClient())
    WriteMessage(m, client);
}

void WriteMessage(AMessage m, OpenWebClient client)
{
  using (var scope = new TransactionScope())
  {
    var audit = GetSomeAuditInfo(AMessage.UserId, client);
    WriteTheMessage(AMessage, client);
    WriteAudit(audit, client);
    client.SetTime(DateTime.Now);
    scope.Commit();
  }  
}

AuditRecord GetSomeAuditInfo(Int userId, OpenWebClient client)
{
  var result = client.ReadAuditRecord(userId);
  return AuditRecord.FromWeb(result);
}

void WriteTheMessage(AMessage msg, OpenWebClient client)
{
  using (var scope = new TransactionScope())
  {
    client.WriteTheMessage(msg.ToWeb());
    scope.Commit();
  }
}

void WriteAudit(AuditRecord audit, OpenWebClient client)
{
  using (var scope = new TransactionScope())
  {
    client.WriteAudit(audit.ToWeb());
    scope.Commit();
  }
}

      

example WCF service

[ServiceContract]
interface IService
{
  [OperationContract]
  void WriteTheMessage(WebRecord message);

  [OperationContract]
  WebRecord ReadAuditRecord(int userId);

  [OperationContract]
  void WriteAudit(WebRecord audit);
}

class MyWebService : IService
{
  [OperationBehavior(TransactionScopeRequired = true)]
  void IService.WriteTheMessage(WebRecord record)
  {
    using (var connection = GetOpenConnection())
    {
      dowritethings;
    }
  }

  [OperationBehavior(TransactionScopeRequired = false)]
  WebRecord IService.ReadAuditRecord(WebRecord record)
  {
    using (var connection = GetOpenConnection())
    {
      return readthings;
    }
  }

  [OperationBehavior(TransactionScopeRequired = true)]
  void IService.WriteAudit(WebRecord record)
  {
    using (var connection = GetOpenConnection())
    {
      dowritethings;
    }
  }
}

      

+3


source to share


2 answers


I went through a web search on how to view the status of an external transaction and came up with the Transaction.Current property, which I entered into the viewport. This showed Aborted after one call to the external function, which I missed completely. Upon entering into this, I found that I had caused a return; from the function between the creation of the transaction and its commit, hence abort.



thanks for the help

+2


source


Every connection you open on the server is a distributed entity. By chance, you often get the same physical connection from the connection pool during your tests. This is such a frustrating behavior because it forces you not to find the problem during testing. This setting behaves in a non-deterministic way relative to the database.

You should have distributed transactions here anyway, because WCF and SQL Server are different resources. This should determine the escalation of MSDTC usage.

I am assuming the transaction came back before this



Likely. With WCF Transactions, your code always has an external transaction configured. There was probably some kind of exception in there somewhere that you didn't notice. Install a debugger to trap all exceptions. Use Fiddler to watch what responses are sent over the wire. Perhaps they contain some kind of error. WCF tracing is another option.

If that doesn't go anywhere, try to create reliable reprogramming. Often you will find an error in this process.

+1


source







All Articles