Interpreter

May 30, 2011 Design Patterns 4 comments

Some imaginary company has very funny business, when people have garage sales, they go and buy everything they can fit into few of their trucks. In the end of the day they are very interested to know how much goods inside of each of the trucks cost. We don’t really care what they do after. But we are interested in knowing how they calculate cost of goods. Many things they buy are packed into packages, sometimes they put similar goods into one package, sometimes they double-triple pack fragile things. So company deals with trucks stuffed with packages of goods. The other day truck’s guts can hit different cost number. In the context of current date prices, having graph of packages/goods we can calculate total cost, this can be done by man, but company goes different way, trucks do it automatically. Each truck accumulates cost of each package, each package calculates cost of what’s inside (packages/goods), any stuff knows its today’s price.
INTERPRETER
Interpreter is design pattern that allows to represent language grammar and knows how to evaluate its sentences into parts that can be understood.
Talking about our dummy example, language would be truck/packages/goods, its current sentence would be stuffed truck ‘cause it has graph of language parts, and the meaning of the sentence would be total cost of the goods inside.
There are two kinds of expressions in the language, those that can be understood immediately, called terminal expressions, and those that require language logic to be applied to be understood, called nonterminal expressions.
Talking about our example, terminal expression would be old TV, Laptop or Bed, since we know that today old TV costs 100, Laptop 500 and Bed 400, and nonterminal expression would be package in which they put 3 laptops, where we have to apply logic to understand what it means to us.
Let’s take a look at our example source code:
Here are expressions our language contains:
    // Abstract expression
    public abstract class Goods
    {
        public abstract int Interpret(CurrentPricesContext context);
    }

    // Nonterminal expression
    public class GoodsPackage : Goods
    {
        public List<Goods> GoodsInside { get; set; }

        public override int Interpret(CurrentPricesContext context)
        {
            var totalSum = 0;
            foreach (var goods in GoodsInside)
            {
                totalSum += goods.Interpret(context);
            }
            return totalSum;
        }
    }

    // Terminal expression
    internal class TV : Goods
    {
        public override int Interpret(CurrentPricesContext context)
        {
            int price = context.GetPrice("TV");
            Console.WriteLine("TV: {0}", price);
            return price;
        }
    }

    // Here other terminal expressions go (Laptop, Bed)
As you can see GoodsPackage knows that for to be understood it has to accumulate cost of each things inside. In our example we have very simple language with only one rule for it, but in more complex languages we will have something different, like for math it could be (“+”, “-”, “/”, “*”, “Sqrt”, “Integral”, and so on…). Math would also have variety of terminal expressions, like numbers or variables, value of which can be substituted.
Two more things are left. It is context, which represent information global to the whole process, in our example prices as of today, and it is client, which actually somehow gets sentence and invokes method Interpret in order to understand sentence. Here below is only Client, I do not show CurrentPricesContext, since it would bring only noise to this example.
        public void RunInterpreterDemo()
        {
            // create syntax tree that represents sentence
            var truckWithGoods = PrepareTruckWithGoods();
            // get latest context
            var pricesContext = GetRecentPricesContext();
            // invoke Interpret
            var totalPriceForGoods = truckWithGoods.Interpret(pricesContext);

            Console.WriteLine("Total: {0}", totalPriceForGoods);
        }

        private CurrentPricesContext GetRecentPricesContext()
        {
            var pricesContext = new CurrentPricesContext();
            pricesContext.SetPrice("Bed", 400);
            pricesContext.SetPrice("TV", 100);
            pricesContext.SetPrice("Laptop", 500);
            return pricesContext;
        }

        public GoodsPackage PrepareTruckWithGoods()
        {
            var truck = new GoodsPackage() { GoodsInside = new List<Goods>() };

            var bed = new Bed();
            var doubleTriplePackedBed = new GoodsPackage() { GoodsInside = new List<Goods>() { new GoodsPackage() { GoodsInside = new List<Goods>() { bed } } } };
            truck.GoodsInside.Add(doubleTriplePackedBed);
            truck.GoodsInside.Add(new TV());
            truck.GoodsInside.Add(new TV());
            truck.GoodsInside.Add(new GoodsPackage() { GoodsInside = new List<Goods>() { new Laptop(), new Laptop(), new Laptop() } });

            return truck;
        }

Quickly output:
Bed: 400

TV: 100

TV: 100

Laptop: 500

Laptop: 500

Laptop: 500

Total: 2100

Interpreter is one of the design patterns that you most likely will never use in your life. It is bit cumbersome and has very specific application.

My Design Patterns Table


4 comments


WCF and versioning – my adventures (or “The resource MultipleIdDefinition was not found”)

May 14, 2011 Errors, WCF No comments

Hey, I believe that everyone of us have ever dealt with versioning. Versioning inside of WCF doesn’t exist if so to say, but it is very easy to keep all your stuff running until you actually have to validate schema of the messages.

In recent time me with my team had to make our Phone client of version 1.0 and 1.1 work with either version of server 1.0 or 1.1. In other words we had 4 cases. Two of them are obviously non-problematic and two are not that clear. Accordingly to MSDN there is no direct support for versioning in WCF, except of that each data elements are optional by default. This means that if you haven’t specified opposite all of your DataMembers are going to be null if they are missed in incoming XML.

So having this in mind I expected that all of our versioning scenarios will go smoothly, but this did not happen. We were getting ugly exception looking like this: “The resource MultipleIdDefinition was not found”. Honestly it was very surprisingly since google search did not give me any good answer for this.

So here are steps that I took to figure out where the problem is:

  • Made the way up to the deserialization code.
  • Debugged to the point where I can see actual payload.
  • For same data request I copied payloads as is from two server versions.
  • Did text comparison and found what I was looking for.

Added properties could not brake serialization, so I found other differences, which were additional z:Id=”i7” right after one of the data contracts. Some of you might know that this is cause of IsReference=true of the DataContract. So I did research if this really has been changed between version 1.0 and 1.1 and found out that it was.

So, long story short, if you having some issues with serialization inside of WCF when dealing with versioning think less about new or even deleted elements of you contract, but think more what can cause mismatch in messages. And dong forget to see source control logs.


No comments


Proxy

May 8, 2011 Design Patterns No comments

Taken from here: http://news.malaysia.msn.com/photogallery.aspx?cp-documentid=4417270&page=7Do you imagine yourself defusing bomb? Scary? Even if you couldn’t imagine this there is such profession as bomb defuser and people owning it are human as well, so I bet they feel scary when near bomb. For our luck there is technology nowadays that allows remotely operate with some kind of robot that can defuse bomb. Using robots also allows to do more complex operations with safely lifting bombs, and manipulating them. I bet human hands would shake while holding bomb, not robot’s.

Connection with robot is wireless of course and you would have special suit that makes you body operate robot remotely as you were it. (Ok on the picture above you see not such advance robot, but lets imagine we are in future.) Robot still has control panel on it that will allow operating it directly. This is needed just in case connection could not be made (say someone is blocking signal).

To summarize, robot is heavy instance and it can be operated directly or you can proxy your requests through special suit.

PROXY

Proxy is design pattern that surrogates real object and proxies requests to it when needed, it also instantiates real object if it is not yet instantiated.

Talking about example above, object which we use is robot (RobotBombDefuser) it is heavy stuff, which we move using remote controls aka. proxy suit (RobotBombDefuserProxy). As this suit works wirelessly with robot it knows how to connect to real object and how to pass your requests to it. The same is happening when we connect to some remote web server and call methods on it.

Proxy is also often used when you need lazy initialization. In this case instead of connecting to remote resource there is simple check if object is not null and then assigning an instance if needed.

Let’s see what we have in our example. Here is robot itself.

    public class RobotBombDefuser
    {
        private Random _random = new Random();
        private int _robotConfiguredWavelength = 41;
        private bool _isConnected = false;

        public void ConnectWireless(int communicationWaveLength)
        {
            if(communicationWaveLength == _robotConfiguredWavelength)
            {
                _isConnected = IsConnectedImmitatingConnectivitiyIssues();
            }
        }
        public bool IsConnected()
        {
            _isConnected = IsConnectedImmitatingConnectivitiyIssues();
            return _isConnected;
        }
        private bool IsConnectedImmitatingConnectivitiyIssues()
        {
            return _random.Next(0, 10) < 4; // immitates 40% good connection, aka. very bad
        }

        public virtual void WalkStraightForward(int steps)
        {
            Console.WriteLine("Did {0} steps forward...", steps);
        }

        public virtual void TurnRight()
        {
            Console.WriteLine("Turned right...");
        }

        public virtual void TurnLeft()
        {
            Console.WriteLine("Turned left...");
        }

        public virtual void DefuseBomb()
        {
            Console.WriteLine("Cut red or green or blue wire...");
        }
    }

 

Main methods that do the stuff are WalkStraightForward, TurnRight, TurnLeft, DefuseBomb. Methods to connect wirelessly and IsConnected are just for imitating reality of this app. You could omit how it works internally.

Here we have Proxy implementation. It always has reference to real object and often implements same interface if is not derived from object’s class.

    public class RobotBombDefuserProxy : RobotBombDefuser
    {
        private RobotBombDefuser _robotBombDefuser;
        private int _communicationWaveLength;
        private int _connectionAttempts = 3;

        public RobotBombDefuserProxy(int communicationWaveLength)
        {
            _robotBombDefuser = new RobotBombDefuser();
            _communicationWaveLength = communicationWaveLength;
        }

        public virtual void WalkStraightForward(int steps)
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.WalkStraightForward(steps);
        }

        public virtual void TurnRight()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.TurnRight();
        }

        public virtual void TurnLeft()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.TurnLeft();
        }

        public virtual void DefuseBomb()
        {
            EnsureConnectedWithRobot();
            _robotBombDefuser.DefuseBomb();
        }

        private void EnsureConnectedWithRobot()
        {
            if (_robotBombDefuser == null)
            {
                _robotBombDefuser = new RobotBombDefuser();
                _robotBombDefuser.ConnectWireless(_communicationWaveLength);
            }

            for (int i = 0; i < _connectionAttempts; i++)
            {
                if (_robotBombDefuser.IsConnected() != true)
                {
                    _robotBombDefuser.ConnectWireless(_communicationWaveLength);
                }
                else
                {
                    break;
                }
            }
            if(_robotBombDefuser.IsConnected() != true)
            {
                throw new BadConnectionException("No connection with remote bomb diffuser robot could be made after few attempts.");
            }
        }
    }

So our proxy simply redirects requests to real object and before doing so it always ensures that connection is established, and if it is not it establishes it with three attempts and if it couldn’t it then throws an exception.

So let’s see usage:

        public static void Run()
        {
            int opNum = 0;
            try
            {
                var proxy = new RobotBombDefuserProxy(41);
                proxy.WalkStraightForward(100);
                opNum++;
                proxy.TurnRight();
                opNum++;
                proxy.WalkStraightForward(5);
                opNum++;
                proxy.DefuseBomb();
                opNum++;

                Console.WriteLine();
            }
            catch (BadConnectionException e)
            {
                Console.WriteLine("Exception has been caught with message: ({0}). Decided to have human operate robot there.", e.Message);

                PlanB(opNum);
            }
        }

        private static void PlanB(int nextOperationNum)
        {
            RobotBombDefuser humanOperatingRobotDirectly = new RobotBombDefuser();

            if(nextOperationNum == 0)
            {
                humanOperatingRobotDirectly.WalkStraightForward(100);
                nextOperationNum++;
            }
            if (nextOperationNum == 1)
            {
                humanOperatingRobotDirectly.TurnRight();
                nextOperationNum++;
            }
            if (nextOperationNum == 2)
            {
                humanOperatingRobotDirectly.WalkStraightForward(5);
                nextOperationNum++;
            }
            if (nextOperationNum == 3)
            {
                humanOperatingRobotDirectly.DefuseBomb();
            }
        }
    }

In sample code above you can see usage of the defuser proxy, there is also “plan B”, when direct instance of the defuser is created and used. Code might look bit complex, because of that opNum and nextOperationNum noise. I added it to ensure robot continues it work from where it stopped.

Output:

Did 100 steps forward…

Turned right…

Exception has been caught with message: (No connection with remote bomb diffuser robot could be made after few attempts.). Decided to have human operate robot there.

Did 5 steps forward…

Cut red or green or blue wire…

My implementation of this Design Pattern is slightly different from its original implementation in GoF book where you have two derived classes both from some interface or superclass. But I think in real world implementation with deriving from already existing class is more common. For example such proxy is used always you need to have virtual methods for some framework, say mocking framework or ORM framework.

Here is UML for my example:

image

My Design Patterns Table


No comments


Using Distributed Transactions in multitier environment

February 28, 2011 HowTo No comments

In one of my previous posts I wrote that we use Distributed Transactions in our code. This worked just fine till we tested all installed on one machine. But once we installed SQL server on machine1 and our services on machine2 and services that use our services on machine3 we got following error messages:

Inner exception message: Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.

This means that your transaction is distributed but not as much as you wish it to be. So it is not enabled for Network access. You would need to go to Administrative Tools –> Component Services to enable it.

image

Here is everything explained up and down how you Enable Network DTC Access:

http://msdn.microsoft.com/en-us/library/cc753510%28v=ws.10%29.aspx

Also, please keep in mind that you would need to enable it on both machines between which you are distributing your transaction.


No comments


Mediator

February 26, 2011 Design Patterns No comments

Some time have passed since I wrote blog post on GoF Design Pattern. Not sure what are actual reasons for this. I guess passing MS exams, but maybe I was lazy.
I had been thinking about good example for Mediator Design Pattern and could not find anything better than standard example with UI and cooperation of different components, but this was before I thought about neurons and their cooperation and in few moments I realized amazing thing. Our brain is mediator to different body parts. It just amazingly fits description.
Just try to imagine what would happen if each of our body part knows about each other. This means that if you see something great and you want to touch it, your eye has to know about your hands and manipulate them to do this. What if you would need to defense by hands because you got hurt in chest. In this case your chest would need to know about hands and manipulate them. This can be applicable to any part of your body that collects information from world and then some reaction should be done by one or many other body parts. Cooperation many-to-many doesn’t work for our body. But it often happens that developers write code that works just as was described above. Sometimes it works, but sometimes it just creates crappy spaghetti mess. Our body has one central system that does all the analyzing for us and manages reactions. Very often this is good practice for code we write.
MEDIATOR
Mediator is design pattern that centralizes cooperation between components thus decoupling interaction between them.
Mediator gracefully simplifies understanding of interaction between components. This gives better maintainability for future, but because logic is centralized it can become very complex and huge, as human brain is.
Here below is demonstration of the demo application I wrote:
image
So as you can see brain know how to handle different things and how to react on them and with which body parts. How does this happen?
Brain (Mediator) knows about each body part (Colleague), so it actually has properties or fields, like Ear, Eye, Hand, Leg, etc. Each of the body parts knows its brain and can signal that something has happened.

Colleague base class (knows its brain)

        // Colleague
        class BodyPart
        {
            private readonly Brain _brain;

            public BodyPart(Brain brain)
            {
                _brain = brain;
            }

            public void Changed()
            {
                _brain.SomethingHappenedToBodyPart(this);
            }
        }

Concrete implementation of Colleague can look as following:

    class Ear : BodyPart
    {
        private string _sounds = string.Empty;

        public Ear(Brain brain)
            : base(brain)
        {
        }

        public void HearSomething()
        {
            Console.WriteLine("Enter what you hear:");
            _sounds = Console.ReadLine();

            Changed();
        }

        public string GetSounds()
        {
            return _sounds;
        }
    }

So it basically can HearSomething and can provide its status by GetSounds method. Some other body parts can have some reactions, as simple Face implementation below:

    class Face : BodyPart
    {
        public Face(Brain brain)
            : base(brain)
        {
        }

        public void Smile()
        {
            Console.WriteLine("FACE: Smiling...");
        }
    }

Mediator (aka Brain)

As it should be expected Mediator is bit huge class and it has to handle all the complexity of interaction between body parts. You might want to change something in this class, I do not expect you to see this as ideal brain, but I hope you get an idea how it works.
    // Mediator
    class Brain
    {
        public Brain()
        {
            CreateBodyParts();
        }

        private void CreateBodyParts()
        {
            Ear = new Ear(this);
            Eye = new Eye(this);
            Face = new Face(this);
            Hand = new Hand(this);
            Leg = new Leg(this);
        }

        public Ear Ear { get; private set; }
        public Eye Eye { get; private set; }
        public Face Face { get; private set; }
        public Hand Hand { get; private set; }
        public Leg Leg { get; private set; }

        public void SomethingHappenedToBodyPart(BodyPart bodyPart)
        {
            if (bodyPart is Ear)
            {
                string heardSounds = ((Ear)bodyPart).GetSounds();

                if (heardSounds.Contains("stupid"))
                {
                    // attacking offender
                    Leg.StepForward();
                    Hand.HitPersonNearYou();
                    Leg.Kick();
                }
                else if (heardSounds.Contains("cool"))
                {
                    Face.Smile();
                }
            }
            else if (bodyPart is Eye)
            {
                // brain can analyze what you see and
                // can react appropriately using different body parts
            }
            else if (bodyPart is Hand)
            {
                var hand = (Hand)bodyPart;

                bool hurtingFeeling = hand.DoesItHurt();
                if (hurtingFeeling)
                {
                    Leg.StepBack();
                }

                bool itIsNice = hand.IsItNice();
                if (itIsNice)
                {
                    Leg.StepForward();
                    Hand.Embrace();
                }
            }
            else if (bodyPart is Leg)
            {
                // leg can also feel something if you would like it to
            }
        }
    }

Personally I liked example that I’ve prepared. Hope there is no such example over internet, but who knows.

UML

In addition here below is some UML stuff. You can click on image to see it bigger.

image

My design patterns table


No comments


I’m MCPD: Enterprise Application Developer 3.5

February 18, 2011 Certification, Success 3 comments

So far so good, I passed everything I planned to pass for the next 1.5 years. Take a look at the picture in career plan for software engineer blog post. I guess that I probably was afraid about learning ASP.NET. And as I passed everything sooner I can plan for more cool stuff, for instance starting my own small project or spend more time on personal life.

But here is just a little bit more on exam itself. I was ready for this exam not because of some books, training kits or anything else. It is all my experience. I extremely enjoyed passing this exam, you just apply your experience and common sense if you have it in software development of enterprise applications. Exam measures my understanding of designing application, its components, their testing, stabilizing, deployment, also choosing appropriate technologies. That is what I encounter often at work.

 

MCPD(rgb)_1260

This is good plus to my CV and promotion strategy.

Exam 70-565: PRO: Designing and Developing Enterprise Applications Using the Microsoft .NET Framework 3.5

I passed 70-565 exam with score 971 out of 1000. And this time exam questions just flattered to me. I liked them much. I believe that this is because they are not kind of questions where you have to know exact method signature. These are questions where you have to think and choose appropriate decision, and even more, they overlap a lot with questions I encountered in my experience.

You can see my transcript using this information:
https://mcp.microsoft.com/authenticate/validatemcp.aspx
Transcript ID: 904316
Access Code: andriybuday

Nearest certification plans

There is still one thing left. It is 4.0 .NET framework outside, not 3.5 so I’m looking for upgrade of the current certification. The best matching exam would be transition of my skills to MCPD 4.0 Windows Developer (70-521). At the moment I don’t have exact date for this exam, but it might be in 2-4 weeks.


3 comments


That’s enough for post suggestion poll on my blog–RESULTS

February 11, 2011 Blog 2 comments

 

Here below are results of the poll that have been on my blog:

image

Obviously people want me to write more on software design and patterns and no one wants to see “Hello World” applications. I’ve been thinking about this poll that it might be that I misses something related to frameworks and new technologies/languages. I’m afraid that those are valuable options as per me.

Anyway, that isn’t so much bad, 24 people have voted and I appreciate all of the votes. I will try to be stick to it, but cannot promise that I will have everything in proportion. Actually I’m planning to have 24 book reviews this year. This means 48 posts on design patterns and software design. Hm.. not that many. Smile

Thank you very much.


2 comments


Bind two values into one text box

February 10, 2011 Silverlight 4 comments

Today I’ve spent some time on playing with some piece of code that had to ensure that on screen in some NumericTextBox depending on situation we show one of the two values – either one automatically calculated or either another user entered.

If value was automatically calculated we show it in that text box, but if user changes it we still keep calculated value untouched (double? CalculatedMileage) but work with another value (double? EnteredMileage). As you see we cannot bind any of these directly to the view.

So, how do we bind two sources (fields) to one target (textbox) on the UI?

I came to some solution with which I’m not completely satisfied, but at least I like it much more than it was before my changes.

Here is binding (I did not change it):

<UserControls:NumericTextBox AllowDecimals=”True”
                             Minimum=”0″ UseMinimum=”True”
                             Maximum=”999.999″ UseMaximum=”True”
                             MaxLength=”6″
                             Value=”{Binding Mileage, Mode=TwoWay}”


Now, Mileage property that I’m binding to the view has backing field _mileage, so I always get value for displaying by using simple getter. But on set I’m actually populating two fields _mileage and EnteredMileage like below:
        private double? _mileage;
        public double? Mileage
        {
            get
            {
                return _mileage;
            }
            set
            {
                _mileage = value;
                EnteredMileage = value;
                RaisePropertyChanged("Mileage");
            }
        }
This means that once I used setter I touched EnteredMileage.
What I display is _mileage and I when I display is when RaisePropertyChanged gets called. So keeping this in mind I do following stuff on screen setup:
 _mileage = EnteredMileage.HasValue ? EnteredMileage : CalculatedMileage;
 RaisePropertyChanged("Mileage");

If user initially entered some value we start operating with it and don’t touch calculated one, but if he did not, then we show calculated at first.
I may be bothering you, but I’m wondering if you know/see some more elegant solution for this stuff. I guess there must be some. And if there is no such, then use mine…


4 comments


Book Review: “3.5–ADO.NET Training Kit” and passing 70-561 exam

February 10, 2011 Book Reviews, Certification, Success No comments

Training Kit

imageSo I finally finished reading training kit for ADO.NET exam. It is easy to read book with many topics that you probably know or at least heard about if you are using .NET. But besides of standard topics on DataSets, Data Querying, LINQ there are few that represent much more interest at least for me. For me these are chapters about Synchronization Framework, Entity Framework and Data Services (REST). I read them with great pleasure. But unfortunately in book they are covered briefly. Also Data Services are not even included into exam questions. I would also say that unless you are going to pass 561 exam, don’t read this training kit, better find some good tutorials on each of the themes, use MSDN and try everything out.

Exam 70-561: TS: Microsoft .NET Framework 3.5, ADO.NET Application Development

I passed 70-561 exam with score 700 out of 1000 with needed 700 for passing. Yeah, that is damn near to failure. But what is also interest that the more I fill overconfident about the exam the worse score I get. Maybe that is why I failed WinForms for the first time, but passed ASP. Who knows.. This rule probably doesn’t apply to WCF exam. I was confident about it and passed with high score.

You can see my transcript using this information:
https://mcp.microsoft.com/authenticate/validatemcp.aspx
Transcript ID: 904316
Access Code: andriybuday

Nearest certification plans

My current certification situation is as following:
image
So I’m very close to my certification goal which is “MCPD: Enterprise Application Developer 3.5” and I already scheduled 565 exam for Friday Feb 18. As for preparation I really hope that couple of years of experience in Enterprise project are in help for me. Also I pick up “Microsoft Application Architecture Guide” for my reading. I read about first 30 pages and I’m impressed by this book. It is real glue. I like very much things that I read from very first pages. Will see how it goes and be ready for review next week. I believe it will be more comprehensive, since this is not kind of training kit book.


No comments


Distributed transactions with NHibernate

January 31, 2011 NHibernate No comments

Most of our current NHibernate saving methods look like below:

        public void SaveCustomer(CustomerEntity customer)
        {
            var transaction = GetActiveTransaction();

            transaction.Begin();
            try
            {
                // some code
                Session.SaveOrUpdate(customer);

                transaction.Commit();
            }
            catch (Exception e)
            {
                transaction.Rollback();
                throw e;
            }
        }

this works great if you need to save just Customer or just Vendor. But in recent time we got kindof challenge to save Customer and Vendor at once in scope of one transaction for piece of functionality, and at the same time method should work for another piece of functionality.
For this we change our methods as following:

        public void SaveVendor(VendorEntity vendor)
        {
            using (var scope = new TransactionScope(TransactionScopeOption.Required)) // if there is no transaction scope, new will be created...
            {
                using (var transaction = Session.BeginTransaction())
                {
                    // some code
                    Session.SaveOrUpdate(vendor);

                    transaction.Commit();
                }
                scope.Complete();
            }
        }

Now we can utilize our methods higher in the call stack:

        public void SaveBunchOfInformationAtOnce(CustomerEntity customer, VendorEntity vendor)
        {
            try
            {
                using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew)) // always new transaction will be created
                {
                    CustomersRepository.SaveCustomer(customer);

                    VendorsRepository.SaveVendor(vendor);

                    scope.Complete();
                }
            }
            catch(Exception e)
            {
                // log errors...
                throw;
            }
        }

This all works just fine both for existing method calls and for new one. Hope it helps.
Next thing that I might need to put into place is to distribute transactions through WCF services. That should be fun.


No comments