ASP.NET3.5 企业级项目开发 -- 第二章(续) 数据访问层(DAL)的开发解决方案提出...
??????????????????ASP.NET3.5 企業(yè)級項目開發(fā) -- 第二章(續(xù)) 數(shù)據(jù)訪問層(DAL)的開發(fā)解決方案提出
???????前言:首先給大家說聲"對不起",因為自從打算寫這系列的文章以來,得到大家很多的支持,謝謝大家!最近因為公司的事和朋友找工作的事,沒有怎么接著寫了,也調(diào)了大家的胃口,還希望園子里的朋友原諒!
???????本篇主要是講述數(shù)據(jù)層的開發(fā),之前的一篇文章已經(jīng)給出了很多的選中的方案,如SqlHelper,DataTable/DataSet,以及自定義實體。但是我們說過了,那些方案都有不盡人意的地方,所以我們就提出用Linq,找個方案就比之前好一些,但是也不是那么完美了。
?
???????本篇的話題如下:
???????Linq中自定義方法
???????提出解決方案
???????Linq中自定義方法
???????在此之前,我們先要講清楚一個問題:在Linq中的自定義存儲過程。
???????我們知道,當(dāng)我們把數(shù)據(jù)庫中的一張表拖放到Linq的ORM設(shè)計器上以后,ORM就自動生成了很多的方法,如Delete,Update,Insert方法,這些方法都是自動生成的,一般是沒有什么問題的,但是一個項目的開發(fā)中,很多時候我們都要把這些方法進(jìn)行定制。那么我們就要用自己的存儲過程。
???????一般情況下,我們可以在我們的數(shù)據(jù)庫中定義一些的存儲過程,如下,我們在之前定義的ENTUserAccount表中添加一條數(shù)據(jù):
?
CREATE?PROCEDURE?ENTUserAccountInsert
?(
??@WindowsAccountName?varchar(50),
??@FirstName?varchar(50),
??@LastName?varchar(50),
??@Email?varchar(100),
??@IsActive?bit,
??@InsertENTUserAccountId?int
?)
?AS
?SET?NOCOUNT?ON
?INSERT?INTO?ENTUserAccount(WindowsAccountName,?FirstName,?LastName,
??Email,?IsActive,?InsertENTUserAccountId,?InsertDate,
???UpdateENTUserAccountId,?UpdateDate)
?VALUES?(@WindowsAccountName,?@FirstName,?@LastName,?@Email,
?@IsActive,?@InsertENTUserAccountId,?GetDate(),
??@InsertENTUserAccountId,?GetDate())
?RETURN
?
???????我們接來進(jìn)行下面的操作;
???????1.把這個存儲過程拖放到ORM設(shè)計器的右邊的方法面板中,這樣存儲過程就自動的生成一個方法。
???????2.在ORM中點(diǎn)擊ENTUserAccount表,選擇屬性中的Insert,如圖:(插圖出現(xiàn)問題,大家原諒!!!)
?
???????3.在出現(xiàn)的面板中,我們選擇Customer(自定義)。選擇我們之前由存儲過程實生成的的方法,確認(rèn)就OK了。
???????如果我們在我們的以后的代碼中調(diào)用HRPaidTimeOffDataContext.InsertENTUseAccount方法,那么此時我們就實際上調(diào)用我們自定義的方法了,之前自動生成的Insert方法就不調(diào)用了。
?
???????同理,Update,Delete方法的自定義也是一樣的。
?
???????提出解決方案
???????約定:我們以后的存儲過程的命名采用方式:表名+操作,如ENTUserAccountInsert。
???????首先我們創(chuàng)建一下存儲過程:
???????ENTUserAccount表中插入數(shù)據(jù)
?
CREATE?PROCEDURE?[dbo].[ENTUserAccountInsert]
?(
??@ENTUserAccountId?int?OUTPUT,
??@WindowsAccountName?varchar(50),
??@FirstName?varchar(50),
??@LastName?varchar(50),
??@Email?varchar(100),
??@IsActive?bit,
??@InsertENTUserAccountId?int
?)
?AS
?SET?NOCOUNT?ON
??INSERT?INTO?ENTUserAccount?(WindowsAccountName,?FirstName,
???LastName,?Email,?IsActive,?InsertDate,
???InsertENTUserAccountId,?UpdateDate,
???UpdateENTUserAccountId)
??VALUES?(@WindowsAccountName,?@FirstName,?@LastName,
???@Email,?@IsActive,?GetDate(),
???@InsertENTUserAccountId,?GetDate(),
???@InsertENTUserAccountId)
??SET?@ENTUserAccountId?=?Scope_Identity()
??RETURN
?
?
???????ENTUserAccount表中更新數(shù)據(jù)
?
?
CodeCREATE?PROCEDURE?[dbo].[ENTUserAccountUpdate]
?(
??@ENTUserAccountId?int,
??@WindowsAccountName?varchar(50),
??@FirstName?varchar(50),
??@LastName?varchar(50),
??@Email?varchar(100),
??@IsActive?bit,
??@UpdateENTUserAccountId?int,
??@Version?timestamp
?)
?AS
?SET?NOCOUNT?ON
?UPDATE?ENTUserAccount
?SET?WindowsAccountName?=?@WindowsAccountName
??,?FirstName?=?@FirstName
??,?LastName?=?@LastName
??,?Email?=?@Email
??,?IsActive?=?@IsActive
??,?UpdateDate?=?GetDate()
??,?UpdateENTUserAccountId?=?@UpdateENTUserAccountId
?WHERE?ENTUserAccountId?=?@ENTUserAccountId
?AND?Version?=?@Version
?RETURN?@@ROWCOUNT
?ENTUserAccount表中刪除數(shù)據(jù)
?
?CREATE?PROCEDURE?[dbo].[ENTUserAccountDelete]
?(
??@ENTUserAccountId?int
?)
?AS
?SET?NOCOUNT?ON
?DELETE?FROM?ENTUserAccount
??WHERE?ENTUserAccountId?=?@ENTUserAccountId
?RETURN
?
?
????????獲取ENTUserAccount表中所有記錄
?
?CREATE?PROCEDURE?ENTUserAccountSelectAll
?AS
?SET?NOCOUNT?ON
?SELECT?ENTUserAccountId,?WindowsAccountName,?FirstName,?LastName,
??Email,?IsActive,?InsertDate,?InsertENTUserAccountid,
??UpdateDate,?UpdateENTUserAccountId,?Version
?FROM?ENTUserAccount
?RETURN
?
???????通過ENTUserAccountId來查找記錄
?
?
CREATE?PROCEDURE?ENTUserAccountSelectById
?(
??@ENTUserAccountId?int
?)
?AS
?SET?NOCOUNT?ON
?SELECT?ENTUserAccountId,?WindowsAccountName,?FirstName,?LastName,
??Email,?IsActive,?InsertDate,?InsertENTUserAccountid,
??UpdateDate,?UpdateENTUserAccountId,?Version
??FROM?ENTUserAccount
??WHERE?ENTUserAccountId?=?@ENTUserAccountId
?RETURN
?
??????? 以前的存儲過程沒有和大家以前做的項目一樣,是很普通的一些存儲過程。
???????寫完上面的存儲過程之后,大家把Insert,Update,Delete的存儲過程拖到ORM的方法面板中生成方法,然后按照我們之前說的方法定制,把ENTUserAccount的Update,Insert等方法都配置成為我們自己寫的方法。
???????注意:對于Select的存儲過程,我們不應(yīng)該把它們直接拖到方法面板中,我們而是把ENTUserAccountSelectAll,ENTUserAccountSelectById存儲過程拖到到ORM設(shè)計器中的ENTUserAccount表上。因為只有這樣,自定生成的代碼才返回ENTUserAccount類的類型;如果是像之前那樣拖到方法面板中,那么返回值就是ISingle<ENTUserAccount>,大家之后會看到原因的。
?
???????之前,我們就在V2.PaidTimeOffDAL中創(chuàng)建一個文件夾,命名為Framework。讓后在這個文件夾下面添加一個類,命名為IENTBaseEntity.cs
?
Code?namespace?V2.PaidTimeOffDAL.Framework
?{
??public?interface?IENTBaseEntity
??{
???DateTime?InsertDate?{?get;?set;?}
???int?InsertENTUserAccountId?{?get;?set;?}
???DateTime?UpdateDate?{?get;?set;?}
???int?UpdateENTUserAccountId?{?get;?set;?}
???Binary?Version?{?get;?set;?}
??}
?}
?
???????因為Binary 類型是在System.Data.Linq下的,所以我們在類中添加這個命名空間的引用。
?
???????大家在想:為什么我們要定義這么一個接口?
?
???????原因有兩點(diǎn):
???????1.因為我們的這個項目中之后會有審計跟蹤的功能,就是說數(shù)據(jù)庫中記錄的每次修改都會記錄下是誰在什么時候修改的,而且我們的所有的表中都會有上面的5個字段。定義接口這樣做為了使得每個類都必需定義必需有上面的5個字段。
???????2.定義接口,可以實現(xiàn)一些依賴倒置的原則,以后大家會看到效果的。
?
???????添加完上面的類之后,那么我們就再添加一個類:CustomizedEntities.cs ,這個類不在Framework文件夾中,而是直接加在外面的。
?
?using?V2.PaidTimeOffDAL.Framework;?namespace?V2.PaidTimeOffDAL
?{
??public?partial?class?ENTUserAccount?:?IENTBaseEntity?{?}
?}
?
???????大家可能會想:ENTUserAccount類是個partial類,那么就說明這個類之前已經(jīng)在什么地方有了的?
???????不錯!我們之前說要把ENTUserAccountById的存儲過程拖到ENTUserAccount表上,其實我們就是想生成這個和數(shù)據(jù)表同名的ENTUserAccount類。
?我們使得這個類實現(xiàn)這個接口,那么我們以后就可以"針對接口編程"。
???????其實我們知道我們的DAL數(shù)據(jù)層的功能很明了:和數(shù)據(jù)庫直接打交道,實現(xiàn)增,刪,改,查操作。
?
???????為了使得我們所有的數(shù)據(jù)操作統(tǒng)一,我們定義了一個基類,以后的所有數(shù)據(jù)庫操作類都實現(xiàn)它。
???????我們在Framework文件夾中添加類:ENTBaseData.cs
?
?
public?abstract?class?ENTBaseData<T>?where?T?:?IENTBaseEntity
?{
??public?abstract?List<T>?Select();
??public?abstract?T?Select(int?id);
??public?abstract?void?Delete(HRPaidTimeOffDataContext?db,?int?id);
??public?void?Delete(string?connectionString,?int?id)
??{
???using?(HRPaidTimeOffDataContext?db?=?new
????HRPaidTimeOffDataContext(connectionString))
???{
????Delete(db,?id);
???}
??}
?}
?
?
??????類的編寫也不難理解:就是有寫操作數(shù)據(jù)的方法。大家還要注意一點(diǎn):Delete方法的實現(xiàn),我們采用了Template Method設(shè)計模式,也就是常說的"鉤子方法",實現(xiàn)的原因,現(xiàn)在講述不是很好理解,沒有一種自然的過程,我以后會說的。
?
???????這樣我們就定義這樣的一個基類,然后針對每個表都有數(shù)據(jù)操作,那么我們就讓每個表的數(shù)據(jù)操作類都繼承這個基類。
???????注意:大家在上面的基類中,沒有看到Insert和Update方法,只是有原因的。如果我們在基類中寫了Insert方法,就會傳入一個T參數(shù),如下:
?????
?
???????這樣是沒有錯,但是不是很好。如果我們的entUseAccount中如果有寫字段沒有賦值,那么我們插入就出問題。
???????所以我們的實現(xiàn)方法是:直接在不同的數(shù)據(jù)操作類中,針對特定的表寫Insert和Update方法。
?
???????我們就來看看ENTUserAccount數(shù)據(jù)表的操作類的實現(xiàn):
?
public?class?ENTUserAccountData?:?ENTBaseData<ENTUserAccount>
?????{
????????
????????public?override?List<ENTUserAccount>?Select()
????????{
????????????using?(HRPaidTimeOffDataContext?db?=?new?HRPaidTimeOffDataContext(DBHelper.GetHRPaidTimeOffConnectionString()))
????????????{
????????????????return?db.ENTUserAccountSelectAll().ToList();????????????????
????????????}
????????}
????????public?override?ENTUserAccount?Select(int?id)
????????{
????????????using?(HRPaidTimeOffDataContext?db?=?new?HRPaidTimeOffDataContext(DBHelper.GetHRPaidTimeOffConnectionString()))
????????????{
????????????????return?Select(db,?id);
????????????}
????????}
??
???????上面方法很簡單:直接調(diào)用自動生成的方法。
?
???????至于DBHelper.GetHRPaidTimeOffConnectionString()方法,就是把數(shù)據(jù)庫的鏈接字符串從web.config文件中讀出。
?
???????下面我們就來看看Delete方法的實現(xiàn):
?
??public?override?void?Delete(HRPaidTimeOffDataContext?db,?int?id)????????{
????????????db.ENTUserAccountDelete(id);
????????}
?
???????我們之前說過,只是一個Template Method模式的使用,使用的意圖是:把具體實現(xiàn)延遲到子類。可能在以后的項目中,我們的數(shù)據(jù)庫要更改了,表也改了,那時,我們的 ENTUserAccount數(shù)據(jù)表可能改為User表,那么我們之前實現(xiàn)的代碼不變,只要重寫Delete方法就行了,如
?
????????{
????????????db.?User?Delete(id);
????????}
?
?
???????下面,我們就來看看Insert方法:
???????其實實現(xiàn)也很簡單,我們采用和SqlHelper相同的方式:第一個方法傳入HRPaidTimeOffDataContext ,第二個方法傳入connectionString
?
???????而且我們傳入的參數(shù)是和ENTUserAccount表相對應(yīng)的字段,這樣就比只是傳入一個ENTUserAccount類要好。
?
Codepublic?int?Insert(string?connectionString,?string?windowsAccountName,?string?firstName,
????????????string?lastName,?string?email,?bool?isActive,?int?insertUserAccountId)
????????{
????????????using?(HRPaidTimeOffDataContext?db?=?new?HRPaidTimeOffDataContext(connectionString))
????????????{
????????????????return?Insert(db,?windowsAccountName,?firstName,?lastName,?email,?isActive,?insertUserAccountId);
????????????}
????????}
????????public?int?Insert(HRPaidTimeOffDataContext?db,?string?windowsAccountName,?string?firstName,?
????????????string?lastName,?string?email,?bool?isActive,?int?insertUserAccountId)
????????{
????????????Nullable<int>?entUserAccountId?=?0;
????????????db.ENTUserAccountInsert(ref?entUserAccountId,?windowsAccountName,?firstName,?lastName,?
????????????????email,?isActive,?insertUserAccountId);
????????????return?Convert.ToInt32(entUserAccountId);
????????}
????????同理,Update方法實現(xiàn)如下;
?
?
Code?public?bool?Update(string?connectionString,?int?userAccountId,?string?windowsAccountName,
????????????string?firstName,?string?lastName,?string?email,?bool?isActive,?int?updateUserAccountId,
????????????Binary?version)
????????{
????????????using?(HRPaidTimeOffDataContext?db?=?new?HRPaidTimeOffDataContext(connectionString))
????????????{
????????????????return?Update(db,?userAccountId,?windowsAccountName,?firstName,?lastName,?email,
????????????????????isActive,?updateUserAccountId,?version);
????????????}
????????}
????????public?bool?Update(HRPaidTimeOffDataContext?db,?int?userAccountId,?string?windowsAccountName,?
????????????string?firstName,?string?lastName,?string?email,?bool?isActive,?int?updateUserAccountId,?
????????????Binary?version)
????????{
????????????int?rowsAffected?=?db.ENTUserAccountUpdate(userAccountId,?windowsAccountName,?firstName,?
????????????????lastName,?email,?isActive,?updateUserAccountId,?version);
????????????return?rowsAffected?==?1;
????????}
?
???????
??????到這里,我們的DAL的實現(xiàn)的示例就到這里,當(dāng)然,我們這里只有一個表,但是我們通過這個示例知道了我們之后實現(xiàn)方法,其他表的實現(xiàn)數(shù)據(jù)操作的方式一樣的,隨著深入的講述,大家會看到的!
?? 為了大家交流,已經(jīng)創(chuàng)建企業(yè)項目開發(fā)團(tuán)隊,希望大家也以后會把有關(guān)企業(yè)開發(fā)的文章放入團(tuán)隊中,希望大家積極參加這個團(tuán)隊。而且我以后也會發(fā)表更多的項目示例,大家一起學(xué)習(xí)進(jìn)步!
???????注:大家留言后,我手動的添加。因為dudu說只能這樣添加,現(xiàn)在博客園團(tuán)隊的功能很有限,只能手動添加成員!
總結(jié)
以上是生活随笔為你收集整理的ASP.NET3.5 企业级项目开发 -- 第二章(续) 数据访问层(DAL)的开发解决方案提出...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pku acm 2248 addti
- 下一篇: oracle简单对象类型