大家好,又见面了,我是你们的朋友全栈君。
只要涉及到数据库的操作,那么使用事务就是难免的。如果我们使用LINQ to SQL作为数据访问层,那么LINQ提供的SubmitChanges()方法自身就包含了对事务的处理。当然,我们也可以利用System.Data.Common.DbTransaction对事务进行处理,我们可以调用DataContext中Connection的方法BeginTransaction()启动事务,然后根据情况进行回滚或提交。例如是这样一段代码:
LinqSampleDataContext context = new LinqSampleDataContext();<br />System.Data.Common.DbTransaction trans = null;<br />try<br />{<br /> context.Connection.Open();<br /> trans = context.Connection.BeginTransaction();<br /> context.Transaction = trans;</p>
<p> context.Employees.InsertOnSubmit(emp);<br /> context.SubmitChanges();</p>
<p> trans.Commit();<br />}<br />catch (Exception ex)<br />{<br /> if (trans != null)<br /> {<br /> trans.Rollback();<br /> }<br />}
然而,当我们在使用LINQ to SQL中时,往往会同时使用多个DataContext,此时我们就需要使用TransactionScope。例如:
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))<br /> {<br /> try<br /> {</p>
<p> for (int i = 0; i < nominees.Count; ++i)<br /> {<br /> Backup newBackup = nominees[i];<br /> Ticket ticket = tickets[i];</p>
<p> //update the information of ticket<br /> //mainly add the information of employee;<br /> ticket.EmployeeID = newBackup.EmployeeID;<br /> ticket.HaveNominated = true;<br /> ticket.IsConfirmedByManager = true;<br /> ticket.Status = TicketStatus.Enroll.ToString();</p>
<p> ticketAccessor.Update(ticket);<br /> }</p>
<p> //update the IsSubmit of backup;<br /> ChangeSubmitStatue(backup);</p>
<p> //remove the record of nominee in backup table<br /> Delete(nominees);<br /> }<br /> catch (Exception ex)<br /> {<br /> ThrowHelper.ThrowBackupException(“Finalizing occurs an error. The transcation will be rollback.”);<br /> return false;<br /> }</p>
<p> scope.Complete();<br /> }
代码中,分别涉及到Update, Delete等操作,因此我们势必需要用事务,保证数据整体提交或整体回滚。在使用事务的时候,有一些前置条件是必备的。例如启动Distributed Transaction Coordinator服务,否则,就会抛出System.Data.SqlClient.SqlException异常,信息为:”MSDTC on server ‘{Server Name}’ is unavailable.”。是的,很多资料都是这样描述的。然而,现实并没有这么简单。我们首先得考虑运行代码的机器是否与数据库所在的机器是同一台。这里所谓的启动Distributed Transaction Coordinator服务,实际上是要启动数据库服务器的服务。如果数据库与代码服务器是同一台,通过这样的设置就没有错误了。
当数据库与代码服务器分属两台机器呢?同样运行如上的代码,就会抛出System.Transactions.TransactionManagerCommunicationException异常。异常信息为:”Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.”
这是一种通信错误,原因在于两台服务器之间的安全配置禁止了分布式事务。解决办法是在运行代码的服务器上,配置Component Services。方法如下: 1、在Run运行窗口中,输入dcomcnfg命令,这样就可以打开Component Services。 2、选择Component Services->Computers->My Computer; 3、右键单击My Computer,在弹出的快捷菜单中,选择“Properties”,然后点击MSDTC tab; 4、在MSDTC tab中,点击Security Configuration按钮; 5、在弹出的对话框中参照下表的建议进行设置:
Configuration Option | Default Value | Recommended Value |
---|---|---|
Network DTC Access | Disabled | Enabled |
Client and Administration | ||
Allow Remote Clients | Disabled | Disabled |
Allow Remote Administration | Disabled | Disabled |
Transaction Manager Communication | ||
Allow Inbound | Disabled | Enabled |
Allow Outbound | Disabled | Enabled |
Mutual Authentication Required | Enabled | Enabled if all remote machines are running Win2K3 SP1 or XP SP2 or higher, and are configured with “Mutual Authentication Required”. |
Incoming Caller Authentication Required | Disabled | Enabled if running MSDTC on cluster. |
No Authentication Required | Disabled | Enabled if remote machines are pre-Windows Server 2003 SP1 or pre- Windows XP SP2. |
Enable TIP | Disabled | Enabled if running the BAM Portal. |
Enable XA Transactions | Disabled | Enabled if communicating with an XA based transactional system such as when communicating with IBM WebSphere MQ using the MQSeries adapter. |
最后的设置如截图:
如果操作系统是Windows 2003,通常默认的设置就是正确的。不过我们在编写程序时,不管是Unit Test,还是其他测试,最频繁的还是在本机上运行。如果操作系统是Windows XP,就不得不进行这样的设置了。
注: 此贴中没写在防火墙中加入msdtc.exe,值得商榷
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/161957.html原文链接:https://javaforall.cn