0

I have got the following code:

aClass.DoAJob();
bClass.DoAnotherJob();
cClass.DoAThirdJob();

I would like it to behave like a database transaction, ie. either all of them execute or none. Any suggestions?

NB This has nothing to do with multithreading or the like. It is just general code.

Antediluvian
  • 653
  • 1
  • 6
  • 18
  • 1
    Can you clarify what you're asking? What does each method do, for example? – ProgrammingLlama Jul 12 '19 at 06:15
  • Probably wants the operation to be atomic and roll back if it fails – arynaq Jul 12 '19 at 06:16
  • @arynaq Yes, I understood that. Thanks. – ProgrammingLlama Jul 12 '19 at 06:18
  • @John like read some configs, update databases and then generate files. – Antediluvian Jul 12 '19 at 06:19
  • you can use TransactionScope to achieve this; refer this, https://stackoverflow.com/questions/224689/transactions-in-net – Abhinaw Kaushik Jul 12 '19 at 06:21
  • 2
    Suppose DoAJob does a Console.WriteLine, and then DoAThirdJob fails. How are you planning on un-ringing that bell? The user may have already read the console. – Eric Lippert Jul 12 '19 at 06:24
  • @AbhinawKaushik I thought that TransactionScope was for SQL commands? Am I mistaken? – ProgrammingLlama Jul 12 '19 at 06:25
  • 3
    It may be helpful for you to understand how databases achieve atomicity. Do you understand how a two-phase commit works? – Eric Lippert Jul 12 '19 at 06:26
  • @EricLippert I guess the console can just output something like 'output regenerated'. By understanding the 2PC, does that mean C# doesn't have such a general purpose transaction infrastructure and I have to create my own? – Antediluvian Jul 12 '19 at 06:39
  • @AbhinawKaushik MSDN seems to only given examples on database transactions with `TransactionScope` even though that thread says it can be used for general purpose. I am not sure about it. – Antediluvian Jul 12 '19 at 06:44
  • @Antediluvian _"does that mean C# doesn't have such a general purpose transaction infrastructure"_ The example given by Eric shows that such a general purpose transactional infrastructure wouldn't make much sense. So, yes: You want it, you code it. – Fildor Jul 12 '19 at 06:46

1 Answers1

2

The general method for making a "transaction" is like this:

  1. Preserve the old data in place
  2. Write the new data to a temporary area
  3. Perform an atomic operation to replace the old data with the new, e.g. by updating a pointer.

For in-memory operations, this is achieved trivially by using an object reference to point to state:

class Program
{

    static Point _position; //Points to latest position of something

    static void Move(int x, int y)
    {
        var temp = new Point(x, y);
        _position = temp;
    }
}

This example allows the program to move an object while guaranteeing that x and y are updated together.

For non-memory operations, the implementation of this pattern is specific to the medium. For example, for file operations, the program might write to a temporary file. When all operations are complete, the program would rename the file to the path expected by the user. This is probably how your browser's download feature works.

A similar mechanism exists for graphics (a frame buffer) and audio (audio buffer). And of course databases have their own particular mechanism that supports atomicity and concurrency, among other things.

John Wu
  • 50,556
  • 8
  • 44
  • 80