Friday, July 8, 2011

Removing Duplicate Transaction Management Code

There is a method called WrapInTransaction on RemotingObjectBase that you should use to add transaction management to code in the remoting facade.

Instead of writing

public void RaiseBirthdayEvents ()
{
    StartTransaction (IsolationLevel.ReadCommitted, "RaiseBirthdayEvents");
    bool committed = false;    

    try
    {
        List<int> personIds = Accessors.PersonDA.FetchPersonIdsByBirthDt (Services.DateService.Today.Month, Services.DateService.Today.Day);            
        foreach (int personId in personIds)
        {
            Services.EventingService.RaiseEvent (EventType.Birthdate, Services.DateService.Today, Table.Person, personId);
        }        

        CommitTransaction ();
        committed = true;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

you can now write
public void RaiseBirthdayEvents ()
{
    WrapInTransaction ("RaiseBirthdayEvents", () => 
    {
        List<int> personIds = Accessors.PersonDA.FetchPersonIdsByBirthDt (Services.DateService.Today.Month, Services.DateService.Today.Day);

        foreach (int personId in personIds)
        {
            Services.EventingService.RaiseEvent (EventType.Birthdate, Services.DateService.Today, Table.Person, personId);
        }
    });
}

Similarly if the code being wrapped needs to return a value, then
public int CreateProlinkManualApplication ()
{
    bool committed = false;
    StartTransaction (IsolationLevel.ReadCommitted, "CreateApplication");

    try
    {
        ApplicationEntity application = ApplicationEntity.Create ();
        application.SaleSourceId = (int) SaleSource.ProsperityApplicationForm;
        Adapter.SaveEntity (application);

        CommitTransaction ();
        committed = true;

        return application.ApplicationId;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}
becomes
public int CreateProlinkManualApplication ()
{
    return WrapInTransaction ("CreateApplication", () =>
    {
        ApplicationEntity application = ApplicationEntity.Create ();
        application.SaleSourceId = (int) SaleSource.ProsperityApplicationForm;
        Adapter.SaveEntity (application);                                               

        return application.ApplicationId;
    });
}
Finally here is the code for the two overloads of the wrapping method:
protected void WrapInTransaction (
    string transactionName,
    Action action)
{
    StartTransaction (IsolationLevel.ReadCommitted, transactionName);
    bool committed = false;

    try
    {
        action.Invoke ();

        CommitTransaction ();
        committed = true;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

protected T WrapInTransaction <T> (
    string transactionName,
    Func<T> function)
{
    StartTransaction (IsolationLevel.ReadCommitted, transactionName);
    bool committed = false;

    try
    {
        T result = function.Invoke ();

        CommitTransaction ();
        committed = true;

        return result;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

No comments:

Post a Comment