简体   繁体   中英

Pitfalls when sharing IDbConnection in ServiceStack

I have a service that use several repositories. I want them all to use the same transaction so that, if anything goes wrong, I can rollback the transactions and nothing is left in an invalid state in the database.

I've created a connection factory that returns the same connection to all clients.

public IDbConnection Connection => _db ?? (_db = _factory.OpenDbConnection());

Repositories takes the class holding this property as a constructor argument. This seemingly works, and enables them to use the same connection, and I can manage the transaction on the outer level. Both the connection factory and its clients are registered in IoC with ReuseScope.Request .

I am wondering though, are there any pitfalls to this?

What happens if someone™ starts using async/await with this shared connection? Do I have to ensure that the connection is never shared across threads? (I was thinking about storing it in a ThreadLocal inside the connection factory).

Anything else?

I'm sorry for this kind of vague question, but I believe this must be a quite common use case.

ADO.NET's IDbConnection resource instance is not thread safe and should never be used in multiple threads. Typically each Thread would retrieve its own pooled DB Connection from the Db connection factory.

Whilst async/await can continue on a different thread, they're not executed concurrently so the same DB Connection can be used as it doesn't get used by multiple threads at the same time.

When I do use repositories they would be responsible for logical units of functionality, (never per-table which I consider an anti-pattern forcing unnecessary friction and abstraction penalties), so I'd rarely have transactions spanning multiple repositories, if I did I'd make it explicit and pass the same DB connection to each repository within an explicit DB transaction scope, eg:

public object Any(MyRequest request)
{
    using (var dbTrans = Db.OpenTransaction())
    {
        MyRepository1.Something(Db, request.Id);
        MyRepository2.Something(Db, request.Id);
        //....

        dbTrans.Commit();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM