System.Transaction:
.net提供的一個(gè)使用很簡單的解決方法。System.Transaction允許對local和distributed數(shù)據(jù)庫進(jìn)行操作。使用System.Tansaction不用考慮是一個(gè)或者多個(gè)connection,一個(gè)或多個(gè)數(shù)據(jù)庫。例如可以使用TransactionScope,舉個(gè)例子,下面的code很直觀,
using (TransactionScope scope = new TransactionScope())
{
SqlConnection connection1 = new SqlConnection(connectString1)
SqlConnection connection2 = new SqlConnection(connectString2)
scope.Complete();
}
有兩個(gè)connection,System.Transaction會(huì)整合成一個(gè)tranaction來處理,那么我們只需要在業(yè)務(wù)層需要transaction的地方使用TransactionScope就可以了,很方便。雖然方便,但還是有不利的地方。因?yàn)镾ystem.Transaction會(huì)自動(dòng)監(jiān)測connection,如果只有一個(gè),就直接使用ado.net的transaction,perfomance不會(huì)影響。但如果是上面的code,有兩個(gè)以上的connection,System.Transaction會(huì)自動(dòng)升級(jí)為distributed級(jí)別,這樣performance會(huì)打了折扣。而且對于除sqlserver一些其他的數(shù)據(jù)庫例如oracle,一直會(huì)是distributed級(jí)別。
這種方式只適合對于performance要求不是很高的項(xiàng)目。
Connection/Transaction參數(shù)傳遞給DAO:
這種方式的思路是DAO的對象每一個(gè)對象需要提供一個(gè)參數(shù)來接受是否需要transaction的信息。例如可以自定義一個(gè)MyTrans類,MyTrans類引用一個(gè)connection對象。
public class MyTrans
{
public IConnection connection;
public void beginTrans();
public void commitTrans();
}
這樣一個(gè)包裝過的類,就可以使業(yè)務(wù)層的對象對connection間接的進(jìn)行操作,例如業(yè)務(wù)層類customer.Update()就可以這樣實(shí)現(xiàn)。
using(MyTrans tran=new MyTrans)
{
tran.beginTrans();
CustomerDAO dao=new CustomerDAO(tran);
dao.Add();
tran.commitTrans();
}
這樣實(shí)現(xiàn),對開發(fā)的復(fù)雜度會(huì)增大,DAO需要每個(gè)類都要實(shí)現(xiàn)一個(gè)接受Trans的參數(shù)。這種方式適和那種有充足時(shí)間而且想親自操作數(shù)據(jù)庫的項(xiàng)目。
AOP實(shí)現(xiàn)Transaction:
這種方式可以參考Spring提供的AOP機(jī)制與Spring的Transation,Aop的內(nèi)部實(shí)現(xiàn)是采用了反射原理,利用Typebuilder對Class的Methord進(jìn)行重新編排,使在邏輯層的對象方法內(nèi)部自動(dòng)的加入Connection的transaction的操作。Spring提供了一個(gè)聲明的方式,很方便快捷,而且由于使用的Ado.net進(jìn)行操作,所以performance沒有受到任何影響。如以下Code,只要簡單的聲明就可以了。
public class TestObjectManager : ITestObjectManager
{
// Fields/Properties ommited
[Transaction()]
public void SaveTwoTestObjects(TestObject to1, TestObject to2)
{
TestObjectDao.Create(to1.Name, to1.Age);
TestObjectDao.Create(to2.Name, to1.Age);
}
[Transaction()]
public void DeleteTwoTestObjects(string name1, string name2)
{
TestObjectDao.Delete(name1);
TestObjectDao.Delete(name2);
}
}
這種方式適合項(xiàng)目較大,需要快速開發(fā),而且項(xiàng)目決策者愿意使用工具的項(xiàng)目。