C# controlling a transaction across multiple databases

后端 未结 2 2104
生来不讨喜
生来不讨喜 2020-11-29 06:30

Say I\'m having a Windows Form application which connected to n databases, with n connections opened simultaneously.

What

相关标签:
2条回答
  • 2020-11-29 07:17

    It seems you may be re-inventing TransactionScope. Doing all this under a unit of work is straightforward*:

      using (TransactionScope scope = new TransactionScope())
      {
         ... Do Stuff with Connection 1 using SqlDataReader
         ... Do Stuff with Connection 2 using Entity Framework
         ... Do Stuff with Connection 3 on another Oracle Database
         ... And for good measure do some stuff in MSMQ or other DTC resource
         scope.Complete(); // If you are happy
      }
    

    Stuff doesn't need to be inline at all - it can be in a different class, or a different assembly. There's no need to explicitly register database or queue connections with the TransactionScope - everything happens automagically, provided that the resources you use are able to enlist into an ambient transaction.

    Now the small print:

    • * Any time you use more than one database connection concurrently, or different connection strings, or multiple technologies, this will require 2 phase commit and escalate to a DTC transaction in order to ensure ACID across the resources. DTC itself has lots more small print and poses many more challenges in a corporate network, like firewalls, clustering, security configuration and bugs.
    • However, with Lightweight transactions on MS Sql Server, if you can keep all your connections using the same database and same connection string settings, and close each connection before opening the next, then you can avoid DTC.

    • Maintaining a transaction across multiple ACID resources will invariably maintain locks on these resources, until the transaction is committed or rolled back. This often doesn't make for good neighbourliness in a high volume enterprise, so be sure to consider the consequences of the locking.

    • If the Stuff is done across multiple threads, you'll need to rope in DependentTransaction

    • A last point worth mentioning is the default isolation level with TransactionScope is Serializable, which is prone to deadlocks. In most non-critical scenarios you'll probably be able drop this down to Read Committed.

    0 讨论(0)
  • 2020-11-29 07:19

    use TransactionScope, it will take care of committing or rolling back all included transactions:

    using (var ts = new TransactionScope())
    {
       ... // your old code
    
       ts.Complete()
    }
    
    0 讨论(0)
提交回复
热议问题