✏️ Explanatory Question

How does exception handling work inside a transaction (ttsbegin…ttscommit) in Dynamics 365 Finance & Operations? Explain the throw / try / catch / finally flow, why you should not call ttsAbort, and how to catch a generic exception.

👁 3 Views
📘 Detailed Answer
🟢 Easy
No previous question
No next question
💡

Answer with Explanation

D365 F&O • X++ INTERVIEW

Exception Handling in Transactions (Dynamics 365 Finance & Operations)

Question 24 — throw / try / catch / finally, automatic rollback, and why you avoid ttsAbort.

Interview Question

How does exception handling work inside a transaction (ttsbegin…ttscommit) in Dynamics 365 Finance & Operations? Explain the throw / try / catch / finally flow, why you should not call ttsAbort, and how to catch a generic exception.

Model Answer (Short)

In D365 F&O you raise errors with throw and handle them with try / catch / finally. The key point about transactions is that when an exception is thrown inside a ttsbegin…ttscommit block and caught outside the transaction, the framework automatically rolls back the whole transaction — so you generally do not call ttsAbort yourself (it's considered an anti-pattern). A catch block cannot be placed inside the same transaction scope it protects; it must sit at a lower tts level. To catch everything you catch System.Exception, and you handle specific recoverable cases like Deadlock and UpdateConflict with retry.

Detailed Explanation

How it behaves in a transaction

  • A thrown exception inside ttsbegin…ttscommit triggers an automatic rollback when caught outside the transaction.
  • The catch block must be at a lower tts level than the transaction it guards — you can't catch within the same open transaction.
  • Recoverable exceptions like Deadlock and UpdateConflict are handled with retry.
  • finally always runs — ideal for cleanup that must happen regardless of success/failure.
GOLDEN RULE
Exception throwncaught outside ttsautomatic rollback (no ttsAbort)

Why avoid ttsAbort

  • The framework already rolls back the transaction automatically on a caught exception.
  • Explicit ttsAbort is redundant and considered an anti-pattern in D365 F&O.
  • It can mask the real error flow and complicate nested transactions.
  • Let exceptions propagate and rely on automatic rollback instead.

Prerequisites (Rule 5)

  • Visual Studio with the Dynamics 365 developer tools.
  • A custom model / package for your objects.
  • A transaction scope (ttsbegin/ttscommit) around the data changes.
  • The #OCCRetryCount macro if you use retry with a bounded count.

Code Example — Catching a generic exception

System.Exception ex;

try
{
    ttsbegin;

    // ... data operations ...

    ttscommit;
}
catch (ex)
{
    // Read message/stack from the .NET exception
    str message = strFmt("@AbcLabels:GenericError", ex.get_Message());
    error(message);
}

Handling deadlock & update conflict with retry

#OCCRetryCount

try
{
    ttsbegin;
    // ... update / delete ...
    ttscommit;
}
catch (Exception::Deadlock)
{
    retry;   // simply retry on deadlock
}
catch (Exception::UpdateConflict)
{
    if (xSession::currentRetryCount() >= #RetryNum)
    {
        throw Exception::UpdateConflictNotRecovered;
    }
    else
    {
        retry;
    }
}

Using finally for guaranteed cleanup

AbcResource res = new AbcResource();

try
{
    ttsbegin;
    res.doWork();
    ttscommit;
}
catch (Exception::Error)
{
    error("Operation failed; transaction rolled back automatically.");
}
finally
{
    // Always runs — release the resource no matter what
    res.close();
}

Common Exception Types to Catch

Exception Meaning Typical handling
Exception::Error General error thrown via throw error() Log / show message
Exception::Deadlock SQL deadlock victim retry
Exception::UpdateConflict OCC RecVersion mismatch retry with count guard
System.Exception Any .NET/CLR exception Catch-all last resort

Points the interviewer wants to hear

  • An exception caught outside the tts scope triggers automatic rollback.
  • Do not call ttsAbort — it's redundant and an anti-pattern.
  • You can't catch inside the same open transaction; catch at a lower tts level.
  • Handle Deadlock / UpdateConflict with retry (bounded).
  • finally always runs — use it for cleanup.

Likely Follow-up Questions

  • Why is ttsAbort discouraged in D365 F&O?
  • Why can't a catch block sit inside the same transaction it protects?
  • Which exceptions are recoverable with retry?
  • When would you catch System.Exception versus a specific type?

Key Takeaway

In D365 F&O, throwing an exception inside a transaction and catching it outside the tts scope rolls everything back automatically — so skip ttsAbort. Handle recoverable deadlocks and update conflicts with a bounded retry, and use finally for guaranteed cleanup.

No previous question
No next question