問題:
1、業(yè)務邏輯與數(shù)據(jù)庫已分離的情況下,怎樣保證每個方法訪問到最適當?shù)臄?shù)據(jù)(不會造成數(shù)據(jù)庫大數(shù)據(jù)量查詢)
2、業(yè)務邏輯與數(shù)據(jù)庫已分離的情況下,如何處理事務
三層結(jié)構(gòu)下,數(shù)據(jù)訪問層與業(yè)務邏輯分離。從對象關(guān)系角度看,業(yè)務邏輯層的對象依賴于數(shù)據(jù)訪問層。.net平臺提供了ado.net對數(shù)據(jù)庫進行操作,connection對象提供了對database連接與transaction的功能。在分層結(jié)構(gòu)下,數(shù)據(jù)訪問層處理了對數(shù)據(jù)庫的操作,實現(xiàn)了domain每一個對象與database的方法。例如對象Customer,提供CustomerDAO.Add(),CustomerDAO.Update()等等的方法,每一個方法都會引用獨立的connection對象。業(yè)務層直接調(diào)用CustomerDAO的方法。connection對象對業(yè)務層是close狀態(tài),業(yè)務層不能訪問到并且控制ado.net提供的transaction。在不破壞分層體系結(jié)構(gòu)前提下一般有三種方式來實現(xiàn)。
System.Transaction:
.net提供的一個使用很簡單的解決方法。System.Transaction允許對local和distributed數(shù)據(jù)庫進行操作。使用System.Tansaction不用考慮是一個或者多個connection,一個或多個數(shù)據(jù)庫。例如可以使用TransactionScope,舉個例子,下面的code很直觀,
using (TransactionScope scope = new TransactionScope())
{
SqlConnection connection1 = new SqlConnection(connectString1)
SqlConnection connection2 = new SqlConnection(connectString2)
scope.Complete();
}
有兩個connection,System.Transaction會整合成一個tranaction來處理,那么我們只需要在業(yè)務層需要transaction的地方使用TransactionScope就可以了,很方便。雖然方便,但還是有不利的地方。因為System.Transaction會自動監(jiān)測connection,如果只有一個,就直接使用ado.net的transaction,perfomance不會影響。但如果是上面的code,有兩個以上的connection,System.Transaction會自動升級為distributed級別,這樣performance會打了折扣。而且對于除sqlserver一些其他的數(shù)據(jù)庫例如oracle,一直會是distributed級別。
這種方式只適合對于performance要求不是很高的項目。
Connection/Transaction參數(shù)傳遞給DAO:
這種方式的思路是DAO的對象每一個對象需要提供一個參數(shù)來接受是否需要transaction的信息。例如可以自定義一個MyTrans類,MyTrans類引用一個connection對象。
public class MyTrans
{
public IConnection connection;
public void beginTrans();
public void commitTrans();
}
這樣一個包裝過的類,就可以使業(yè)務層的對象對connection間接的進行操作,例如業(yè)務層類customer.Update()就可以這樣實現(xiàn)。
using(MyTrans tran=new MyTrans)
{
tran.beginTrans();
CustomerDAO dao=new CustomerDAO(tran);
dao.Add();
tran.commitTrans();
}
這樣實現(xiàn),對開發(fā)的復雜度會增大,DAO需要每個類都要實現(xiàn)一個接受Trans的參數(shù)。這種方式適和那種有充足時間而且想親自操作數(shù)據(jù)庫的項目。
AOP實現(xiàn)Transaction:
這種方式可以參考Spring提供的AOP機制與Spring的Transation,Aop的內(nèi)部實現(xiàn)是采用了反射原理,利用Typebuilder對Class的Methord進行重新編排,使在邏輯層的對象方法內(nèi)部自動的加入Connection的transaction的操作。Spring提供了一個聲明的方式,很方便快捷,而且由于使用的Ado.net進行操作,所以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);
}
}
這種方式適合項目較大,需要快速開發(fā),而且項目決策者愿意使用工具的項目。
3、事務處理應用Spring.net ,查詢和報表應用PLSQL控制。