日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

ASP.NET3.5 企业级项目开发 -- 第二章 数据访问层(DAL)的开发

發(fā)布時(shí)間:2023/12/9 asp.net 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ASP.NET3.5 企业级项目开发 -- 第二章 数据访问层(DAL)的开发 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??

????????????????????????????????????ASP.NET3.5 企業(yè)級(jí)項(xiàng)目開發(fā) -- 第二章 數(shù)據(jù)訪問層(DAL)的開發(fā)
?
???????前言:本篇主要講述數(shù)據(jù)訪問層的開發(fā),而且為了大家交流,已經(jīng)創(chuàng)建企業(yè)項(xiàng)目開發(fā)團(tuán)隊(duì),希望大家也以后會(huì)把有關(guān)企業(yè)開發(fā)的文章放入團(tuán)隊(duì)中,希望大家積極參加這個(gè)團(tuán)隊(duì)。而且我以后也會(huì)發(fā)表更多的項(xiàng)目示例,大家一起學(xué)習(xí)進(jìn)步!
?
???????本篇的話題主要如下:

???????問題提出
???????設(shè)計(jì)方案
?
???????問題提出
?
???????數(shù)據(jù)訪問層(DAL)的目標(biāo)創(chuàng)建一些以便業(yè)務(wù)層來調(diào)用的類和方法。我們之前總是用GridView來綁定DataSet和DataReader,但是在稍微大點(diǎn)的項(xiàng)目開發(fā)中DAL不能直接和用戶

??????界面打交道。
??????
???????一般來說,DAL是用來和數(shù)據(jù)庫和BLL打交道的,也就是處理BLL和數(shù)據(jù)庫的中間。數(shù)據(jù)以什么形式在DAL和BLL之前傳遞有很多的爭(zhēng)論。不同的人有不同的意見,數(shù)據(jù)傳遞的形式有:DataSet,強(qiáng)類型的DataSet,DataReader,自定義實(shí)體。在介紹Ling to Sql之后,大家心里會(huì)有清晰的答案。在以前的開發(fā)中,我們一般是采用ADO.NET來和數(shù)據(jù)庫打交道,那么就需要我們的開發(fā)人員對(duì)ADO.NET有一定的比較深入的了解,但是當(dāng)我們用Linq to? Sql之后,我們可以很方便的使用DataContext來與數(shù)據(jù)庫拉打交道,而不需要我們懂得很多的ADO.NET的知識(shí),但是在Linq to Sql的背后還是在采用ADO.NET來和數(shù)據(jù)庫交互的。
?
???????還有就是事務(wù)處理的問題。關(guān)于事務(wù)的概念,相信大家都清楚,我也不贅述了。事務(wù)處理在什么地方實(shí)現(xiàn)有如下意見:在存儲(chǔ)過程中直接用SQL語句來寫;在DAL層處理,

??????在BLL層處理。當(dāng)然,每一種的選擇都有各自的理由和利弊。還有一點(diǎn)要注意的是:不要把事務(wù)處理的代碼到處寫,如在DAL層中寫一點(diǎn),在BLL中寫一點(diǎn)。
?
?
?
???????設(shè)計(jì)方案
?
???????在設(shè)計(jì)方案中實(shí)際上就是提供幾個(gè)選擇來解決之前我們提出的問題。以下就是兩個(gè)選擇:

???????1.DAL只要是執(zhí)行CRUD操作,CRUD是就是:Create,Read,Update,Delete.在.NET Framwework中提供了很多和數(shù)據(jù)庫打交道的ADO.NET類和方法,如

SqlConnection,SqlCommand,SqlCommand.ExecuteNonQuery()等,用過ADO.NET的朋友應(yīng)該清楚這些常用的類,我這里也不羅嗦。
?
???????2.SqlHelper
?用過ADO.NET的朋友應(yīng)該知道,在我們開發(fā)過程中,很多時(shí)候?qū)慉DO.NET代碼的時(shí)候,代碼結(jié)構(gòu)和功能都是大同小異的,所以基于此,微軟就開發(fā)了Microsoft Data Access Application Block,只要我們調(diào)用其中的一些方法,傳入一些參數(shù)就行了,不需要我們?cè)偃懩切┓爆嵉腁DO.NET代碼,因?yàn)檫@個(gè)數(shù)據(jù)訪問塊都已經(jīng)封裝好了。其中一個(gè)最重要的類就是SqlHelper.這個(gè)類是個(gè)靜態(tài)類,提供了很多的方法,如下:

???????ExecuteNonQuery
???????ExecuteDataset
???????ExecuteReader
???????ExecuteScalar
???????FillDataset

???????上面 方法的設(shè)計(jì)包含了很多OO的思想。我們來看看ExecuteNonQuery方法 ,其他的方法的設(shè)計(jì)思想和方式一樣的:
?

?

Code
//連接字符串
?public?static?int?ExecuteNonQuery(string?connectionString,?CommandType?commandType,string?commandText)
?{?…?}

?
public?static?int?ExecuteNonQuery(string?connectionString,?CommandType?commandType,string?commandText,?params?SqlParameter[]?commandParameters)
?{?…?}

?
public?static?int?ExecuteNonQuery(string?connectionString,?string?spName,?params?object[]?parameterValues)
?{?…?}

?

?

?

?

Code
?//連接對(duì)象
?public?static?int?ExecuteNonQuery(SqlConnection?connection,?CommandType?commandType,?string?commandText)
?{?…?}

?
public?static?int?ExecuteNonQuery(SqlConnection?connection,?CommandType?commandType,?string?commandText,?params?SqlParameter[]?commandParameters)
?{?…?}

?
public?static?int?ExecuteNonQuery(SqlConnection?connection,?string?spName,?params?object[]?parameterValues)
?{?…?}

?


?

Code
?//事務(wù)對(duì)象
?public?static?int?ExecuteNonQuery(SqlTransaction?transaction,?CommandType?commandType,?string?commandText)
?{?…?}

?
public?static?int?ExecuteNonQuery(SqlTransaction?transaction,?CommandType?commandType,?string?commandText,?params?SqlParameter[]?commandParameters)
?{?…?}

public?static?int?ExecuteNonQuery(SqlTransaction?transaction,?string?spName,?params?object[]?parameterValues)
?{?…?}

?


???????上面前3個(gè)方法都是采用了一個(gè)連接字符串的參數(shù),而接下來的3個(gè)方法是采用了一個(gè)連接對(duì)象為參數(shù),最后的3個(gè)方法采用了一個(gè)事務(wù)對(duì)象為參數(shù)。這些方法在調(diào)用存儲(chǔ)過程時(shí)提供了很大的靈活性。 例如:


?

Code
?CREATE?PROCEDURE?UserAccountInsert(
??
@Name?varchar(50),
??
@UserAccountId?int?OUTPUT
?)
?
AS
?
SET?NOCOUNT?ON
??
INSERT?INTO?UserAccount?(Name)?VALUES?(@Name)
?
SET?@UserAccountId?=?Scope_Identity()

??
?調(diào)用代碼如下:


?

Code
?public?int?InsertUserAccount(string?connectionString,?string?name)
?{
??SqlParameter[]?parameters?
=
??{
???
new?SqlParameter(?"@Name",?SqlDbType.VarChar,?50),
???
new?SqlParameter(?"@UserAccountId",?SqlDbType.Int)
??};
??parameters[
].Value?=?name;
??parameters[
1].Direction?=?ParameterDirection.Output;
??SqlHelper.ExecuteNonQuery(connectionString,CommandType.StoredProcedure,?
"UserAccountInsert",??parameters);
??
return?Convert.ToInt32(parameters[1].Value);
?}

?
?

??????? 還有一個(gè)問題要注意就是更新時(shí)的同步問題。例如,用戶從數(shù)據(jù)庫中獲取一條數(shù)據(jù),然后更改了一些內(nèi)容,之后就保存記錄到數(shù)據(jù)庫中,那么系統(tǒng)就應(yīng)該只保存用戶之前取出的那條數(shù)據(jù)。為了達(dá)到這個(gè)效果,我們可以在每次數(shù)據(jù)更新的時(shí)候添加一個(gè)datetime類型或者int類型的字段來標(biāo)記。當(dāng)我們從數(shù)據(jù)庫中返回一條記錄時(shí),我們?cè)赨I顯示層顯示出來,然后修改數(shù)據(jù),再保存到數(shù)據(jù)庫中,那么我們?cè)跀?shù)據(jù)庫中的存儲(chǔ)過程的SQL語句就只是更新之前我們?nèi)〕龅哪菞l數(shù)據(jù)。在Sql Server 2005中,我們可以用timespan類型的字段來跟蹤和標(biāo)識(shí)每條數(shù)據(jù)的版本,所以sql語句如下:



?

Code
?CREATE?PROCEDURE?UserAccountUpdate(
??
@Name?varchar(50),
??
@UserAccountId?int,
??
@LastUpdateDate?datetime
?)
?
AS
?
UPDATE?UserAccount
??
SET?Name?=?@Name,
??LastUpdateDate?
=?GetDate()
??
WHERE?UserAccountId?=?@UserAccountId
??
AND?LastUpdateDate?=?@LastUpdateDate

?
???????請(qǐng)大家注意LastUpdateDate 字段其實(shí)就是一個(gè)標(biāo)識(shí)每條數(shù)據(jù)版本的輔助字段。
???????調(diào)用的C#代碼如下:
?


Code
?public?bool?UpdateUserAccount(string?connectionString,?string?name,?int?userAccountId,?DateTime?lastUpdateDate)
?{
??SqlParameter[]?parameters?
=
??{
???
new?SqlParameter(?"@Name",?SqlDbType.VarChar,?50),
???
new?SqlParameter(?"@UserAccountId",?SqlDbType.Int),
???
new?SqlParameter(?"@LastUpdateDate",?SqlDbType.DateTime)
??};
??parameters[
].Value?=?name;
??parameters[
1].Value?=?userAccountId;
??parameters[
2].Value?=?lastUpdateDate;
??
int?rowsAffected?=
??Convert.ToInt32(SqlHelper.ExecuteNonQuery(connectionString,
??CommandType.StoredProcedure,?
"UserAccountUpdate",?parameters));
??
return?rowsAffected?==?1;
?}?

?

?

???????下面我們就來看看數(shù)據(jù)在DAL和BLL之間是以什么形式來交換的,一般有以下選擇:
?
???????DataSet
???????類型化的DataSet
???????自定義實(shí)體

?

?

???????當(dāng)BLL類調(diào)用從DAL中的一些方法拉獲取數(shù)據(jù)時(shí),它們將怎樣接受這些數(shù)據(jù)?
???????是用DataSet/DataTable,還是自定義實(shí)體?

???????下面我們就看看給自的優(yōu)缺點(diǎn):
?
???????如果選擇使用DataSet/DataTable在DAL和BLL層之前傳遞數(shù)據(jù),就需要使用ADO.NET中的方法來訪問BLL中的數(shù)據(jù)。如果選擇自定義實(shí)體,那么所有的數(shù)據(jù)將被封裝到自定義實(shí)體類和類的集合中,這樣就可以根據(jù)具體情況來訪問BLL,這中方式更加的自然。
?
???????很多人認(rèn)為DataSet/DataTable對(duì)于基于桌面的只能客戶端程序來說是最好的選擇,但是對(duì)于可擴(kuò)展的高性能Web網(wǎng)站來說,則不夠強(qiáng)大。這里所說的DataSet是指類型化的DataSet,因?yàn)榉穷愋突腄ataSet有很多的確定:進(jìn)行配置和編碼時(shí),很容易把表名,字段名,關(guān)系名,或者字段的類型搞錯(cuò),而且在調(diào)試的時(shí)候花費(fèi)很多的時(shí)間。而類型化的DataSet很容易使用,因?yàn)樗梢允褂弥悄芨袘?yīng)來獲得字段名,而且還內(nèi)置了排序和過濾的功能,執(zhí)行數(shù)據(jù)綁定而且DataSet/DataTable還是可以序列化的,這樣就可以更加容易的傳輸它們。


???????DataSet/DataTable的缺點(diǎn):性能和擴(kuò)展性的局限性,數(shù)據(jù)的表示形式和業(yè)務(wù)規(guī)則驗(yàn)證。如果只需要傳遞一條數(shù)據(jù),那么我們?nèi)匀恍枰獎(jiǎng)?chuàng)建一個(gè)完整的DataSet/DataTable,這就需要系統(tǒng)開銷。而且DataSet/DataTable和數(shù)據(jù)庫的關(guān)于很密切,可以說是內(nèi)存中的數(shù)據(jù)庫,所以DataSet/DataTable沒有一個(gè)清晰的,面向?qū)ο蟮臄?shù)據(jù)表示方式。盡管DataSet/DataTable同IDE集成的很好,但是每次數(shù)據(jù)庫結(jié)構(gòu)發(fā)生變化,如添加字段,重命名等,那么我們就得重新創(chuàng)建類型化的DataSet.最大的問題就是:在DataSet中添加自定義的業(yè)務(wù)和驗(yàn)證邏輯困難。在將它們保存到數(shù)據(jù)庫之前,或者在運(yùn)行其他語句之前要對(duì)那些新記錄強(qiáng)制之心業(yè)務(wù)規(guī)則,需要寫很多的代碼,而且需要深入的了解ADO.NET的知識(shí)。大家要明白?如果使用的是自定義的實(shí)體,那么我們就需要手動(dòng)的把數(shù)據(jù)庫中的表映射為自定義的業(yè)務(wù)類,而且這將是一項(xiàng)麻煩的事情,而且還有一點(diǎn)很之前的DataSet/DataTable一樣:如果數(shù)據(jù)庫中的表結(jié)構(gòu)變化,那么我們又得重新修改我們的自定義的業(yè)務(wù)類,
?
???????我們真的就沒有辦法了嗎?
???????有,絕對(duì)有方法可以解決上面的問題,那么就Linq to Sql 和它的ORM設(shè)計(jì)器。
?
??
???????下面我們就看看Linq to Sql
?
???????注:在本章中,不需要大家對(duì)Linq很熟悉,只要了解就行了,因?yàn)閷?duì)與用到的知識(shí),會(huì)詳細(xì)的講述的。而且大家一定要一步步的跟著做,切記!

???????在VS2008中,一個(gè)改進(jìn)的功能就是Linq還有就是對(duì)象關(guān)系模型(ORM)設(shè)計(jì)器,ORM設(shè)計(jì)器可以自動(dòng)的生成類,并且自動(dòng)進(jìn)行ADO.NET的操作。其中一個(gè)最中要的類就是DataContext,大家可以把這個(gè)類和我們之前談的SqlHelper類來類比,它們都是封裝了數(shù)據(jù)操作的細(xì)節(jié)。
?
?

???????下面請(qǐng)大家跟著我一起來做:
???????1.創(chuàng)建一個(gè)新的Sql Server 2005 數(shù)據(jù)庫,或者直接用VS2008自帶的SQL Exss創(chuàng)建也行,如下:
?
?

?

??????

???????2.數(shù)據(jù)庫名稱為HRPaidTimeOff
???????3.創(chuàng)建ENTUserAccount表,如下:

???????我們?cè)谶@個(gè)項(xiàng)目中的所有表都以ENT為前綴,表明這個(gè)表是可重用企業(yè)級(jí)框架的一部分。還有ENTUserAccountId是identity的。

???????來看看表的定義和字段的意義:這個(gè)表其實(shí)就是一個(gè)用戶賬戶表,其中ENTUserAccountId就是用戶賬戶的ID,也是主鍵,WindowsAccountName就是用戶的計(jì)算機(jī)名稱,FirstName,LastName就是用戶名字,Email用戶郵箱,IsActive表明這個(gè)用戶是否是激活狀態(tài),后面的IsertDate,InsertENTUserAccountId,UpdateDate,UpdateENTUserAccountId,

??????這幾個(gè)字段在我們項(xiàng)目的所有的表中都有的,因?yàn)槲覀冎笠砑訉徲?jì)和跟蹤功能要用到這些字段,它們的意義分別是:用戶添加的時(shí)間,是哪個(gè)用戶添加了當(dāng)前的這個(gè)用戶,用戶更新時(shí)間,是哪個(gè)用戶更新的當(dāng)前用戶。舉個(gè)例子就是:加入Mary是管理員,她添加了一個(gè)Bob用戶,那么ENTUserAccountId就是Bob用戶記錄的主鍵,FirstName就是Bob,InsertENTUserAccountId就是Mary的ID。
?
???????下面我們就添加一條記錄:
???????WindowsAccountName = Lufy
???????FirstName = Yang
???????LastName = Wang
???????Email = yangyang4502@yahoo.com.cn
???????IsActive = True
???????InsertDate=getdate()
???????InsertENTUserAccountId = 1
???????UpdateDate = getdate()
???????UpdateENTUserAccountId = 1

?

???????現(xiàn)在數(shù)據(jù)表就創(chuàng)建好了,打開VS2008創(chuàng)建連接(如果我們之前是直接用VS2008的服務(wù)器資源管理創(chuàng)建的,那么下面的步驟就不用作了,如果使用的 sql 2005,下面的步驟就要做


???????1.在VS2008中選擇"視圖"-"服務(wù)器資源管理"
???????2.點(diǎn)擊"數(shù)據(jù)庫連接",右擊,"添加連接",數(shù)據(jù)庫選擇"Microsoft SQL Server (SqlClient)",服務(wù)器為".\sqlexss".
???????3.選擇身份驗(yàn)證方式為"Windows驗(yàn)證",選擇數(shù)據(jù)庫為"HRPaidTimeOff"
???????4.測(cè)試連接,然后OK
?
???????下面我們就來創(chuàng)建DataContext
???????我們之前說過:DataContext和我們之前談的SqlHelper類來類比,它們都是封裝了數(shù)據(jù)操作的細(xì)節(jié)。我們?cè)赩2.PaidTimeOffDAL項(xiàng)目上右擊,選擇"添加新項(xiàng)",如下:
?

?
???????VS2008自動(dòng)的添加System.Data.Linq的引用,同時(shí)也添加了三個(gè)文件:HRPaidTimeOff.dbml, RPaidTimeOff.dbml.layout和HRPaidTimeOff.designer.cs.其中HRPaidTimeOff.dbml, RPaidTimeOff.dbml.layout將會(huì)被ORM圖形設(shè)計(jì)器所使用,.cs文件包含了所有自動(dòng)創(chuàng)建的類。
?
?
???????大家可以雙擊"HRPaidTimeOff.designer.cs"文件,我們就會(huì)看見VS2008創(chuàng)建的分部類HRPaidTimeOffDataContext,這個(gè)類繼承自System.Data.Linq.DataContext。我們可以用這個(gè)類來和數(shù)據(jù)打交道,就想我們之前使用SqlHelper類一樣。這個(gè)類有一個(gè)名為MappingSource的變量,和一些構(gòu)造函數(shù)。其中構(gòu)造函數(shù)有的采用一個(gè)連接字符串為參數(shù),有的用一個(gè)實(shí)現(xiàn)了IDBConnection接口的類為參數(shù),然后所有的構(gòu)造函數(shù)都調(diào)用了OnCreated方法。

???????打開折疊區(qū)域--"Extensibility Method Definitions",就可以看到下面的方法:


?

partial ? void ?OnCreated();

?

????????這是VS2008的一個(gè)新的語法:分部方法,大家可以和之前的partial class類比。這個(gè)方法允許你在類中先定義方法,然后在該類的其他partial類中實(shí)現(xiàn)方法體。如果我們的partial 方法沒有實(shí)現(xiàn),那么及時(shí)你調(diào)用了這個(gè)方法,也不會(huì)出錯(cuò),因?yàn)榫幾g器會(huì)忽略這個(gè)方法的調(diào)用。
?
???????下面,我們雙擊"HRPaidTimeOff.dbml",就可以看到圖形化的ORM設(shè)計(jì)器。然后,我們展開"服務(wù)器資源管理器"窗口,然后把PaidTimeOff數(shù)據(jù)庫總的ENTUserAccount拖到設(shè)計(jì)器的左邊。如下:
?

?

??????此時(shí),VS2008就直接創(chuàng)建一個(gè)實(shí)體類來映射ENTUserAccount表,再次打開"HRPaidTimeOff.designer.cs"文件,我們可以看到這個(gè)文件和我們之前看到的就不同了,我們首先可以看到下面的Attribute被添加了:
???

????[System.Data.Linq.Mapping.DatabaseAttribute(Name = " HRPaidTimeOff " )]

?
???????而且在"Extensibility Method Definitions:"很多新的方法也添加了:

?

? partial ? void ?InsertENTUserAccount(ENTUserAccount?instance);
?
partial ? void ?UpdateENTUserAccount(ENTUserAccount?instance);
?
partial ? void ?DeleteENTUserAccount(ENTUserAccount?instance);

?

???????而且,一個(gè)新的構(gòu)造函數(shù)也添加了,這個(gè)函數(shù)采用一個(gè)連接字符串為參數(shù)和一個(gè)映射源為參數(shù):

? public ?HRPaidTimeOffDataContext()?: base ( global ::V2.PaidTimeOffDAL.Properties.Settings.DefaultHRPaidTimeOffConnectionString,?mappingSource)
?{
??OnCreated();
?}
?

?

???????除此之外,還有一些類添加了,在解決方案窗口,我們可以看到Settings.settings文件和Settings.Designer.cs文件,打開Settings.Designer.cs文件,我們可以看到這個(gè)類是繼承自global::System.Configuration.ApplicationSettingsBase,有一個(gè)屬性很重要,就是HRPaidTimeOffConnectionString,這屬性返回?cái)?shù)據(jù)庫連接字符串 ,所以在默認(rèn)情況下,我們之前建立的HRPaidTimeOffDataContext的數(shù)據(jù)庫連接字符串在Settings文件中指定。
?
???????我們?cè)倩氐紿RPaidTimeOffDataContext類,我們可以找到一個(gè)ENTUserAccount的類,它就是數(shù)據(jù)庫表的一個(gè)映射類。

???????我們只要了解這么多就行了,下面就通過例子的使用來了解其他的知識(shí)。
?
???????添加數(shù)據(jù)記錄

???????編譯V2.PaidTimeOffDAL,我們?cè)谖覀兘鉀Q方案的那個(gè)網(wǎng)站項(xiàng)目這引用V2.PaidTimeOffDAL.dll,我們這里只是臨時(shí)的使用以下V2.PaidTimeOffDAL.dll而以,大家知道UI層不能直接和DAL打交道的,我們這里暫時(shí)的使用,使得大家對(duì)Linq更加的熟悉一點(diǎn)。
???????大家跟著做:
???????1.在網(wǎng)站項(xiàng)目中添加System.Data.Linq引用。
???????2.在Default.aspx頁面添加一個(gè)按鈕,ID為btnInsert,Text為Insert
???????3.在Default.aspx.cs添加V2.PaidTimeOffDAL引用。
???????4.在Insert按鈕點(diǎn)擊事件下,添加下面代碼:
?
?

Code
protected?void?btnInsert_Click(object?sender,?EventArgs?e)
?{
??
//創(chuàng)建DataContext實(shí)例
??HRPaidTimeOffDataContext?db?=?new?HRPaidTimeOffDataContext();

??
//創(chuàng)建新的ENTUserAccount?對(duì)象,并且設(shè)計(jì)屬性
??ENTUserAccount?userAccount?=?new?ENTUserAccount
??{
???WindowsAccountName?
=?@"VARALLO1\VaralloMadison",
???FirstName?
=?"Madison",
???LastName?
=?"Varallo",
???Email?
=?"madison.varallo@v2.com",
???IsActive?
=?true,
???InsertDate?
=?DateTime.Now,
???InsertENTUserAccountId?
=?1,
???UpdateDate?
=?DateTime.Now,
???UpdateENTUserAccountId?
=?1
??};

??
//傳入數(shù)據(jù)
??db.ENTUserAccounts.InsertOnSubmit(userAccount);

??
//保存到數(shù)據(jù)庫
??db.SubmitChanges();
?}

??????

???????上面的代碼其實(shí)和我們之前使用ADO.NET的形式很接近。首先我們創(chuàng)建一個(gè)連接實(shí)例HRPaidTimeOffDataContext和數(shù)據(jù)庫連接,然后就是創(chuàng)建一條數(shù)據(jù),然后調(diào)用InsertOnSubmit方法插入數(shù)據(jù),最后就保存數(shù)據(jù),db.SubmitChanges()把數(shù)據(jù)保存到數(shù)據(jù)庫中。
?

???????更新數(shù)據(jù)
?
???????在Default.aspx頁面中再添加一個(gè)按鈕,ID為btnUpdate,Text為Update,按鈕事件代碼如下:
?

?

Code
?protected?void?btnUpdate_Click(object?sender,?EventArgs?e)
?{
??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();

??ENTUserAccount?userAccount?
=?db.ENTUserAccounts.Single(u?=>
???u.WindowsAccountName?
==?@"VARALLO1\VaralloMadison");

??userAccount.IsActive?
=?false;
??db.SubmitChanges();
?}

?

??????

???????這個(gè)段代碼和之前的差不多,首先還是實(shí)例化一個(gè)數(shù)據(jù)庫連接的對(duì)象HRPaidTimeOffDataContext ,然后用Lamdal表達(dá)式選出一條數(shù)據(jù),然后更改IsActive =false;最后保存回?cái)?shù)據(jù)庫中。
?
???????大家可以看到,使用Linq以后,我們?cè)僖矝]有用ADO.NET的語句了,而且我們寫代碼的方式也完全改變。
?
?
???????我們從更新數(shù)據(jù)的例子中看到,我們首先從數(shù)據(jù)庫中獲取一條數(shù)據(jù),然后改變數(shù)據(jù),最后再次保存回?cái)?shù)據(jù)庫。對(duì)于Web程序來說用,我們通常從數(shù)據(jù)庫中獲取一條數(shù)據(jù),顯示在界面上,然后用戶更改數(shù)據(jù),然后點(diǎn)擊按鈕回傳到服務(wù)器,那么數(shù)據(jù)就傳到了我們的DAL,DAL取執(zhí)行更新操作。例如,我們把一個(gè)用戶的信息全部取出了,包含F(xiàn)irstName,LastName,Email,IsActive等等,那么我們的界面上面就顯示出來這些數(shù)據(jù),我們假設(shè)是用TextBox來顯示的,那么當(dāng)我們更改了其中一個(gè)數(shù)據(jù),如IsActive,那么我們就點(diǎn)擊按鈕,我們此時(shí)其實(shí)就要把界面上面的所有信息,包括FirstName,LastName,WindowAccountName,Email等全部返回到服務(wù)器(大家想想我們的一般更新的存儲(chǔ)過程是怎樣寫的,就明白了),因?yàn)槿绻覀冎皇欠祷匾粋€(gè)IsActive,服務(wù)器端根本不知道更新那條數(shù)據(jù),此時(shí)我們?cè)诜?wù)器端就應(yīng)該寫下面的代碼:
?
??

Code


?
protected?void?btnUpdate_Click(object?sender,?EventArgs?e)
?{
??
//Create?an?ENTUserAccount?object?and?set?the?properties
??ENTUserAccount?userAccount?=?new?ENTUserAccount
??{
???ENTUserAccountId?
=?2,
???WindowsAccountName?
=?@"VARALLO1\VaralloMadison",
???FirstName?
=?"Madison",
???LastName?
=?"Varallo",
???Email?
=?"madison.varallo@v2.com",
???IsActive?
=?false,
???UpdateDate?
=?DateTime.Now,
???UpdateENTUserAccountId?
=?1

??};

??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();
??db.ENTUserAccounts.Attach(userAccount,?
true);

??db.SubmitChanges();
?}

?

???????這段代碼和之前一樣,也是把IsActive設(shè)置為false,但是我們調(diào)用的是Attach方法,而且把第二個(gè)參數(shù)設(shè)置為true,說明我們要采用更新操作。
?如果運(yùn)行代碼,會(huì)報(bào)錯(cuò)的:
???????An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.
?
???????意思是說,我們回傳的那條記錄在數(shù)據(jù)庫中不存在。

???????這里還有一個(gè)問題要說明:我們確實(shí)是從數(shù)據(jù)庫中獲取一條數(shù)據(jù),然后顯示在界面上,我們更新數(shù)據(jù)后,數(shù)據(jù)要取數(shù)據(jù)庫中更新,那么數(shù)據(jù)庫怎么知道現(xiàn)在我們傳來的數(shù)據(jù)就是之前從數(shù)據(jù)庫中取出的那條呢?

???????所以我們就需要一個(gè)標(biāo)識(shí)或者說是時(shí)間戳,來表明我們現(xiàn)在回傳的數(shù)據(jù)確實(shí)屬于數(shù)據(jù)庫,那么我們就修改我們的數(shù)據(jù)表ENTUserAccount,添加一個(gè)新的字段Version,類型為timespan。所以當(dāng)我們?nèi)?shù)據(jù)的時(shí)候,我們就把數(shù)據(jù)的版本Version字段保存在ViewState中,然后更新數(shù)據(jù)之后,我們把這個(gè)字段一起返回,數(shù)據(jù)庫就檢查我們傳回的Version字段是否和我們要更新的數(shù)據(jù)記錄的Version是否相同,如果相同就更新數(shù)據(jù),如下代碼:
??????

?Page_Load事件中把Version保存:


Code
?protected?void?Page_Load(object?sender,?EventArgs?e)
?{
??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();
??ENTUserAccount?userAccount?
=?db.ENTUserAccounts.Single(ua?=>
??ua.WindowsAccountName?
==?@"VARALLO1\VaralloMadison");
??ViewState[
"ENTUserAccountId"]?=?userAccount.ENTUserAccountId;
??ViewState[
"InsertENTUserAccountId"]?=userAccount.InsertENTUserAccountId;
??ViewState[
"InsertDate"]?=?userAccount.InsertDate;
??ViewState[
"Version"]?=?userAccount.Version;
?}

??????

???????在btnUpdate按鈕事件中,如下:


?

Code
protected?void?btnUpdate_Click(object?sender,?EventArgs?e)
?{
??
//Create?an?ENTUserAccount?object?and?set?the?properties
??ENTUserAccount?userAccount?=?new?ENTUserAccount
??{
???WindowsAccountName?
=?@"VARALLO1\VaralloMadison",
???FirstName?
=?"Madison",
???LastName?
=?"Varallo",
???Email?
=?"madison.varallo@v2.com",
???IsActive?
=?false,
???UpdateDate?
=?DateTime.Now,
???UpdateENTUserAccountId?
=?1
??};

??userAccount.ENTUserAccountId?
=Convert.ToInt32(ViewState["ENTUserAccountId"]);
??userAccount.InsertENTUserAccountId?
=
??Convert.ToInt32(ViewState[
"InsertENTUserAccountId"]);
??userAccount.InsertDate?
=Convert.ToDateTime(ViewState["InsertDate"]);
??userAccount.Version?
=?(Binary)ViewState["Version"];
??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();
??db.ENTUserAccounts.Attach(userAccount,?
true);
??db.SubmitChanges();
?}

?



????????這樣就OK了。如果大家有什么問題,就留言!

???????刪除記錄:
?

Code
protected?void?btnDelete_Click(object?sender,?EventArgs?e)
?{
??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();
??
//Create?an?ENTUserAccount?object
??ENTUserAccount?userAccount?=?new?ENTUserAccount();
??userAccount.ENTUserAccountId?
=
??Convert.ToInt32(ViewState[
"ENTUserAccountId"]);
??userAccount.Version?
=?(Binary)ViewState["Version"];
??db.ENTUserAccounts.Attach(userAccount);
??db.ENTUserAccounts.DeleteOnSubmit(userAccount);
??db.SubmitChanges();
?}

????????方法DeleteOnSubmit是自動(dòng)生成的。我們也可以定制。我們后面談。

???????查詢數(shù)據(jù):
???????我們可以根據(jù)條件查詢,然后綁定:


?

Code
?protected?void?btnSelect_Click(object?sender,?EventArgs?e)
?{
??HRPaidTimeOffDataContext?db?
=?new?HRPaidTimeOffDataContext();
??var?userAccounts?
=
??from?u?
in?db.ENTUserAccounts
??select?u;
??GridView1.DataSource?
=?userAccounts;
??GridView1.DataBind();
?}

?

?

?

??????今天我們就說到這里,談了一些方法和預(yù)備的方案,我們下篇就說說在我們這個(gè)項(xiàng)目DAL到底如何設(shè)計(jì)。

???????為了大家交流,已經(jīng)創(chuàng)建企業(yè)項(xiàng)目開發(fā)團(tuán)隊(duì),希望大家也以后會(huì)把有關(guān)企業(yè)開發(fā)的文章放入團(tuán)隊(duì)中,希望大家積極參加這個(gè)團(tuán)隊(duì)。而且我以后也會(huì)發(fā)表更多的項(xiàng)目示例,大家一起學(xué)習(xí)進(jìn)步!
?


原文鏈接: http://www.cnblogs.com/yanyangtian/archive/2009/05/31/1493014.html

轉(zhuǎn)載于:https://my.oschina.net/dtec/blog/43579

總結(jié)

以上是生活随笔為你收集整理的ASP.NET3.5 企业级项目开发 -- 第二章 数据访问层(DAL)的开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。