.net 系统框架是如何管理事务的?
小灰狼 2020-04-16 10:04:27 本人Java工程师,偶尔做做 .net 下的东东
一直不太明白 dot net 下对事务管理似乎不太关注它们的一致性!
先说说Java的机制。
在Java项目里,特别是 Web 项目里,对数据库事务的管理很多时候都是由框架自动完成的,感觉很方便也很合理。
比如在一个Web项目中,一般是框架把一个数据库连接和当前的线程绑定,这样一来,在程序的任何地方如果想访问数据库,可以通过框架把与当前线程绑定的连接取到,然后访问数据库。当然,这是基本原理,中间还会有很多机制。
这样做的好处是,一方面框架保证了连接的打开和关闭,以前一直困扰程序员的有连接打开却没有关闭的现象不再存在;另一方面是,代码里不必再花太多工夫关注事务了,方法调用方法,然后被调用的方法里又调用其它方法……这些方法访问数据库时,只要是在一个线程里,就肯定是在一个事务里。
但是在 .net 里似乎没有这种机制。以 EntityFramework 为例,如果我没有理解错的话,它是通过一个 Context 对象来管理事务的,在这个 Context 对象上进行的操作才属于同一个事务。
如此一来,前面说的两个问题。事务管理方面,在业务逻辑开始的地方,使用 using(Context ctx = new DefaultContext()) 保证事务的开启和关闭,这需要人工管理;在事务管理方面,如果方法1调用为方法2,则方法1要把一个 Context 对象通过参数传递给方法2,如果方法2调用方法3,也是如此。
当然,我们可以通过程序架构市里时,把 Context 对象或者 Connection 对象进行封装,把它放到线程静态变量中,这样就不必把 Context 或 Connection 对象从方法传来传去!十年前写过一个简单的 asp.net webform 项目,我就是这样管理连接的!
另外,我看一些朋友写的 dot net 系统,他们的做法都没有关注事务的一致性。比如对数据表的插入操作,被封装成一个方法,在这个方法里,临时打开连接,插入操作完成之后马上关闭,打开连接、执行操作、得到结果、关闭连接都在这个方法里完成。如果有一个业务需要连接插入三个表,那么至少会打开三次连接,并且三次插入操作不在同一事务中!一旦插入一、二个表成功,第三个表插入失败,事务无法回滚,业务逻辑会不完整!为此,我曾经问过那些朋友,他们说如果遇到事务,会单独写几个方法,连接进行数据库访问。虽然他的办法可行,但本人感觉总是没那么完善,插入操作要被重写!
想想 dot net 和 Java 竞争了有20年了,没道理在这个问题上会明显的处于下风,并且个人感觉这种问题解决应该不是什么难事!还是说 dot net 在处理数据库事务方面有独特的思想?