当TransactionScope被实例化时,事务管理器需要确定要参与哪个事务。一旦确定,该实例将一直参与到事务中。 在创建TransactionScope对象时,我们需要传递具有以下值的TransactionScopeOption枚举:
Required:实例必须需要事务,如果事务已存在,则使用已存在事务,否则将创建新事务。
RequiresNew:始终为实例创建一个新的事务。
Suppress:创建实例时,其他已存在事务将被抑制,因为该实例内的所有操作的完成而无需其他已存在事务。
接下来我们利用上述枚举中第二种方式来实现航班预约,简单逻辑如下:
public class MakeReservation { FlightDBContext flight; HotelDBContext hotel; public MakeReservation() { flight = new FlightDBContext(); hotel = new HotelDBContext(); } //处理事务方法 public bool ReservTrip(TripReservation trip) { bool reserved = false; //绑定处理事务范围 using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew)) { try { //航班信息 flight.FlightBookings.Add(trip.Filght); flight.SaveChanges(); //预约信息 hotel.Reservations.Add(trip.Hotel); hotel.SaveChanges(); reserved = true; //完成事务并提交 scope.Complete(); } catch (Exception ex) { throw ex; } } return reserved; } }
上述ReservTrip方法接受TripReservation对象。 该方法定义了TransactionScope,并在事务的上下文中捆绑了用于Flight和Hotel的Create操作,并将代码写入try-catch块中。 如果两个实体的SaveChanges方法成功执行,那么事务将被完成,否则回滚。接下来进行控制器调用。
public class TripController : Controller { MakeReservation reserv; public TripController() { reserv = new MakeReservation(); } public ActionResult Index() { return View(); } public ActionResult Create() { return View(new TripReservation()); } [HttpPost] public ActionResult Create(TripReservation tripinfo) { try { tripinfo.Filght.TravellingDate = DateTime.Now; tripinfo.Hotel.BookingDate = DateTime.Now; var res = reserv.ReservTrip(tripinfo); if (!res) { return View("Error"); } } catch (Exception) { return View("Error"); } return View("Success"); } }
我们添加航班预约视图:
@model EntityFrameworkTransactionScope.Data.Entity.TripReservation @{ ViewBag.Title = "Create"; } <h2>旅游出行</h2> @using(Html.BeginForm()){ <table> <tr> <td> <table> <tr> <td colspan="2"> 航班信息 </td> </tr> <tr> <td> 航班Id: </td> <td> @Html.EditorFor(m => m.Filght.FlightId) </td> </tr> <tr> <td> 航班名称: </td> <td> @Html.EditorFor(m => m.Filght.FilghtName) </td> </tr> <tr> <td> 航班号: </td> <td> @Html.EditorFor(m => m.Filght.Number) </td> </tr> </table> </td> <td> <table> <tr> <td colspan="2"> 预约信息 </td> </tr> <tr> <td> 预约Id: </td> <td> @Html.EditorFor(m => m.Hotel.BookingId) </td> </tr> <tr> <td> 客户名称 </td> <td> @Html.EditorFor(m => m.Hotel.Name) </td> </tr> </table> </td> </tr> <tr> <td colspan="2"> <input type="submit" value="提交预约" /> </td> </tr> </table> }
视图展示UI如下:
要运行应用程序并检查事务,我们需要使用分布式事务处理协调器(DTC)服务。 该服务协调更新两个或多个事务受保护资源的事务,例如数据库,消息队列,文件系统等。首先我们需要确保DTC是否已经开启,在服务中进行查看并启用。
接下来打开DTC设置,请按照下列步骤操作或者直接运行【dcomcnfg.exe】一步到位打开组件服务。
打开控制面板
找到管理工具
找到组件服务
接下来我们填写相关信息来进行航班预约。
如上显示已经预约成功,我们看看两个数据库中的数据是否正确插入。