Tutorial :software transactions in c#



Question:

I have some C# code that needs to work like this

D d = new D();  foreach(C item in list)  {      c.value++;      d.Add(c);   // c.value must be incremented at this point  }  if(!d.Process())      foreach(C item in list)          c.value--;  

It increments a value on each item in a list and then tries to do some processing on them. If the processing fails, it needs to blackout the mutation or the items.

The question it: is there a better way to do this? The things I don't like about this is that there are to may ways I can see for it to go wrong. For instance, if just about anything throws it gets out of sync.

One idea (that almost seems worse than the problem) is:

D d = new D();  var done = new List<C>();  try  {      foreach(C item in list)      {          c.value++;          done.Add(c);          d.Add(c);      }      if(d.Process()) done.Clear();  }  finaly  {      foreach(C c in done)          c.value--;  }  


Solution:1

Without knowing the full details of your application, I don't think it's possible to give you a concrete solution to the problem. Basically, there is no method that will always work in 100% of the situations you need something like this.

But if you're in control of the class D and are aware of the circumstance in which D.Process() will fail, you might be able to do one of two things that will make this conceptually easier to manage.

One way is to test D's state before calling the Process method by implementing something like a CanProcess function that returns true if and only if Process would, but without actually processing anything.

Another way is to create a temporary D object that doesn't actually commit, but runs the Process method on its contents. Then, if Process succeeded, you call some kind of Promote or Commit method on it that finalizes the changes. Similar to if you had a Dataset object, you can create a clone of it, do your transactional stuff in the clone, then merge it back into the main dataset if and only if the processing succeeded.


Solution:2

It's memory intensive, but you can make a copy of the list before incrementing. If the process succeeds, you can return the new list. If it fails, return the original list.


Solution:3

Why don't you increment only when the process success?

I think a better way is to make the process method in D increments the c.value inside.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »