Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transactionable objects in C#?

Looking at the code :

class MyClass {  public static int g=1;}

using (TransactionScope tsTransScope = new TransactionScope())
{
    //Do stuff here
    MyClass.g=999;
    tsTransScope.Complete();
}
  • Looking at the "Do stuff here" section : What type of objects can I write in there so they can be Transactionable ?. I already know that I can write ADO commands and they will be rollback/commited when neccesary. But via C# POV : what implementation should a Class has to have in order to be Transactionable ( implementing some interface or something ?)

  • If it is a TransactionScope as it called , inside a using clause (which is try + finally) , The logic says that if there is a rollback : MyClass.g should get BACK its value of 1. however. this is not happening. So I guess it is related to the first question. How can I make MyClass Transactionable ?

like image 822
Royi Namir Avatar asked Dec 30 '12 09:12

Royi Namir


1 Answers

You should implement System.Transactions.IEnlistmentNotification interface, this article and this may help you

For ready-made transactional in-memory storage, there is (Software transactional memory), and STM.NET it is not a final stuff, but Microsoft is working on it!

A small example:

using System.IO;
using System.Text;
using System.Transactions;

namespace Sakher.Transactions
{
    public class TsansactionalFileWriter
    {
        private FileTransactionEnlistment fileTransactionEnlistment = new FileTransactionEnlistment();
        public TsansactionalFileWriter(string filePath)
        {
            fileTransactionEnlistment.FilePath = filePath;
            Transaction.Current.EnlistVolatile(fileTransactionEnlistment, EnlistmentOptions.None);
        }

        public void AppendText(string text)
        {
            fileTransactionEnlistment.Content.Append(text);
        }

        public void WriteAllText(string text)
        {
            fileTransactionEnlistment.Content = new StringBuilder(text);
        }
    }

    public class FileTransactionEnlistment : IEnlistmentNotification
    {
        public string FilePath { get; set; }
        public StringBuilder Content { get; set; }

        public FileTransactionEnlistment()
        {
            Content = new StringBuilder();
        }

        public void Commit(Enlistment enlistment)
        {
            File.WriteAllText(FilePath, Content.ToString());
        }

        public void InDoubt(Enlistment enlistment)
        {

        }

        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            //You can create the file here
            preparingEnlistment.Prepared();
        }

        public void Rollback(Enlistment enlistment)
        {
            //Do ssomething when the transaction is rolled-back (You may delete the file if you have created it!)
        }
    }

}

Consuming the code:

        using (TransactionScope tr = new TransactionScope())
        {
            TsansactionalFileWriter writer = new TsansactionalFileWriter("c:\\myFile.txt");
            writer.AppendText("sdfgssdfgsdf");
            tr.Complete();
        }

* EDTI : ADDED G KEEPER FOR ROYI :) *

using System.Transactions;

namespace Sakher.Transactions
{
    public class  Royi_s_gReturnerClass 
    {
        private GReturnerEnlistment fileTransactionEnlistment = new GReturnerEnlistment();
        public Royi_s_gReturnerClass()
        {
            Transaction.Current.EnlistVolatile(fileTransactionEnlistment, EnlistmentOptions.None);
        }
    }

    public class GReturnerEnlistment : IEnlistmentNotification
    {
        public int GOldValue { get; set; }

        public GReturnerEnlistment()
        {
            GOldValue = MyClass.g;
        }

        public void Commit(Enlistment enlistment)
        {

        }

        public void InDoubt(Enlistment enlistment)
        {

        }

        public void Prepare(PreparingEnlistment preparingEnlistment)
        {
            preparingEnlistment.Prepared();
        }

        public void Rollback(Enlistment enlistment)
        {
            MyClass.g = GOldValue;
        }
    }

}

Your code will be:

class MyClass {  public static int g=1;}

using (TransactionScope tsTransScope = new TransactionScope())
{
    Royi_s_gReturnerClass returner = new Royi_s_gReturnerClass();
    //Do stuff here
    MyClass.g=999;
    tsTransScope.Complete();
}
like image 52
Sawan Avatar answered Nov 17 '22 06:11

Sawan