简体   繁体   English

将事务与业务流程和存储库模式一起使用

[英]Using Transactions with Business Processes and the Repository pattern

I have a situation (I'm guessing is pretty standard) where I need to perform some business calculations and create a bunch of records in the database.我有一种情况(我猜这很标准),我需要执行一些业务计算并在数据库中创建一堆记录。 If anything goes wrong at any point I need to roll everything back from the database.如果在任何时候出现任何问题,我需要从数据库中回滚所有内容。 Obviosly I need some kind of transaction.显然我需要某种交易。 My question is where do I implement transaction support.我的问题是我在哪里实现事务支持。 Here's my example这是我的例子

//BillingServices - This is my billing service layer. called from the UI
public Result GenerateBill(BillData obj)
{
     //Validate BillData

     //Create a receivable line item in the receivables ledger 
     BillingRepository.Save(receivableItem);

     //Update account record to reflect new billing information
     BillingRepository.Save(accountRecord);

     //...do a some other stuff
     BillingRepository.Save(moreStuffInTheDatabase);
}

If any of the updates to the database fail I need to roll the other ones back and get out.如果对数据库的任何更新失败,我需要将其他更新回滚并退出。 Do I just expose a Connection object through my Repository in which I can call我是否只是通过我可以调用的存储库公开一个连接 object

Connection.BeginTransaction() Connection.BeginTransaction()

or do I do I just validate in the service layer and just call one method in the repository that saves all the objects and handles the transaction?还是我只是在服务层中进行验证,然后在存储库中调用一种方法来保存所有对象并处理事务? This doesn't quite seem right to me.这对我来说似乎不太正确。 It's seem like it would force me to put to much business logic in the data layer.似乎它会迫使我在数据层中投入大量的业务逻辑。

What's the right approach?什么是正确的方法? What if I need to span repositories (or would that be bad design)?如果我需要跨越存储库(或者那将是糟糕的设计)怎么办?

I'm assuming that you are using .NET here.我假设您在这里使用 .NET。 That being the case, you can simply wrap the entire code section in a using statement with a TransactionScope instance and it will handle the transaction semantics for you.在这种情况下,您可以简单地将整个代码部分包装在带有TransactionScope实例的using语句中,它将为您处理事务语义。 You simply have to call the Complete method at the end:您只需在最后调用Complete方法

//BillingServices - This is my billing service layer. called from the UI
public Result GenerateBill(BillData obj)
{
     // Create the transaction scope, this defaults to Required.
     using (TransactionScope txScope = new TransactionScope())
     {
          //Validate BillData

          //Create a receivable line item in the receivables ledger 
          BillingRepository.Save(receivableItem);

          //Update account record to reflect new billing information
          BillingRepository.Save(accountRecord);

          //...do a some other stuff
          BillingRepository.Save(moreStuffInTheDatabase);

          // Commit the transaction.
          txScope.Complete();
     }
}

If an exception occurs, this has the effect of not calling Complete when the code block is exited;如果发生异常,这具有退出代码块时不调用Complete的效果; the Dispose method on the TransactionScope implementation of the IDisposable interface is called when the scope of the using statement is exited.当退出using语句的 scope 时,调用IDisposable接口TransactionScope实现上的Dispose方法

In the Dispose call, it checks to see if the transaction completed (this state is set when Complete succeeds).Dispose调用中,它检查事务是否已完成(此 state 在Complete成功时设置)。 If that state isn't set, it performs a rollback.如果 state 未设置,它将执行回滚。

You can then nest this within other TransactionScope instances (deeper in your call stack on the same thread) to create larger transactions across multiple repositories.然后,您可以将其嵌套在其他TransactionScope实例中(在同一线程上的调用堆栈中更深),以跨多个存储库创建更大的事务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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