gjspaho
gjspaho

Reputation: 314

ServiceStack Ormlite transaction between services

I'm having trouble with a rather complex save operation inside a ServiceStack service. To simplify the explanation the service starts an Ormlite transaction and within it calls another service through ResolveService:

public ApplicationModel Post(ApplicationModel request)
{
    using (IDbTransaction tr = Db.OpenTransaction())
    {
        using (var cases = ResolveService<CaseService>())
        {
            request.Case = cases.Post(request.Case);
        }
    }
    Db.Save<Application>(request.Application, true);
}

The other service (CaseService) uses also a transaction to perform its logic:

public CaseModel Post(CaseModel request)
{
    using (IDbTransaction tr = Db.OpenTransaction())
    {
        Db.Insert<Case>(request);
        Db.SaveAllReferences<CaseModel>(request);
    }
}

In a similar situation with higher hierarchy of services calling other services a "Timeout expired" error is thrown, and so far I've not been able to resolve, although I closely monitored the SQL Server for deadlocks.

My question is whether this is the right way of using/sharing Ormlite transactions across services or there is another mechanism?

Thanks in advance.

Upvotes: 4

Views: 846

Answers (1)

mythz
mythz

Reputation: 143284

You shouldn't have nested transactions, rather than calling across services to perform DB operations you should extract shared logic out either using a separate shared Repository or re-usable extension methods:

public static class DbExtensions
{
    public static void SaveCaseModel(this IDbConnection db,
        CaseModel case)
    {
        db.Insert<Case>(case);
        db.SaveAllReferences<CaseModel>(case);
    }
}

Then your Services can maintain their own transactions whilst being able to share logic, e.g:

public ApplicationModel Post(ApplicationModel request)
{
    using (var trans = Db.OpenTransaction())
    {
        Db.SaveCaseModel(request.Case);
        Db.Save<Application>(request.Application, true);
        trans.Commit();
    }
}

public CaseModel Post(CaseModel request)
{
    using (var trans = Db.OpenTransaction())
    {
        Db.SaveCaseModel(request);
        trans.Commit();
    }
}

Upvotes: 3

Related Questions