四十八:對SqlDataSource控件使用開放式并發(fā).docx_第1頁
四十八:對SqlDataSource控件使用開放式并發(fā).docx_第2頁
四十八:對SqlDataSource控件使用開放式并發(fā).docx_第3頁
四十八:對SqlDataSource控件使用開放式并發(fā).docx_第4頁
四十八:對SqlDataSource控件使用開放式并發(fā).docx_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

在ASP.NET 2.0中操作數(shù)據(jù)之四十八:對SqlDataSource控件使用開放式并發(fā)作者:heker2007 字體:增加減小 類型:轉(zhuǎn)載 時間:2016-05-16我要評論本文主要講解ASP.NET 2.0中SqlDataSource控件通過配合SQL語句達(dá)到控制開放式并發(fā)的目的,通過在UPDATE和DELETE語句里擴(kuò)展WHERE字句,SqlDataSource能應(yīng)對絕大部分情況。導(dǎo)言:在前面的教程里,我們考察了如何為SqlDataSource控件添加插入、更新、刪除功能。簡而言之,就是為其nsertCommand, UpdateCommand和DeleteCommd屬性賦以相應(yīng)的INSERT,UPDATE和DELETESQL語句,并將相應(yīng)的參數(shù)放置在, 和標(biāo)簽里。我們可以手工書寫這些代碼,也可以通過在設(shè)置數(shù)據(jù)源向?qū)Ю飭螕簟案呒墶卑粹o,選擇“自動生成INSERT, UPDATE和DELETE命令”,自動的生成語句。在“高級SQL生成選項”對話框里有個“使用開放式并發(fā)”選項(見圖1)。當(dāng)選擇該項后,數(shù)據(jù)庫中的數(shù)據(jù)在自上一次成功保存以來沒發(fā)生任何改變的情況下,才能成功地執(zhí)行更新或刪除操作。圖1:在“高級SQL生成選項”對話框添加開放式并發(fā)支持在實現(xiàn)開放式并發(fā)教程路我們探討了開放式并發(fā)控制的基本原理以及如何對ObjectDataSource控件使用開放式并發(fā)。在本教程我們看如何對SqlDataSource控件使用開放式并發(fā)。新的開放式并發(fā)在一個允許多人同時編輯或刪除相同數(shù)據(jù)的應(yīng)用程序里,有這種可能:一個人修改后的記錄意外地被另一個人修改的記錄所覆蓋。在Implementing Optimistic Concurrency 這篇教程我們例舉過這樣的例子:例如,假設(shè)兩個用戶,Jisun和Sam,都訪問我們的應(yīng)用軟件中的一個頁面,這個頁面允許訪問者通過一個GridView控件更新和刪除產(chǎn)品數(shù)據(jù)。他們都同時點擊GridView控件中的Edit按鈕。Jisun把產(chǎn)品名稱更改為“Chai Tea”并點擊Update按鈕,實質(zhì)結(jié)果是向數(shù)據(jù)庫發(fā)送一個UPDATE語句,它將更新此產(chǎn)品的所有可修改的字段(盡管Jisun實際上只修改了一個字段:ProductName)。在這一刻,數(shù)據(jù)庫中包含有這條產(chǎn)品記錄“Chai Tea”種類為Beverages、供應(yīng)商為Exotic Liquids、等該產(chǎn)品的詳細(xì)信息。然而,在Sam的屏幕中的GridView里,當(dāng)前編輯行里顯示的產(chǎn)片名稱依舊是“Chai”。在Jisun的更改被提交后片刻,Sam把種類更改為“Condiments”并點擊Update按鈕。這個發(fā)送到數(shù)據(jù)庫的UPDATE語句的結(jié)果是將產(chǎn)品名稱更改為“Chai”、CategoryID字段的值是種類Beverages對應(yīng)的ID,等等。Jisun所作的對產(chǎn)品名稱的更改就被覆蓋了。圖2展示了這些連續(xù)的事件圖2:當(dāng)兩個用戶同時更新一條記錄,則存在一個用戶的更改覆蓋另一個的更改的可能性為了應(yīng)對這種可能性,我們必須執(zhí)行某種并發(fā)控制。本文的焦點開放式并發(fā)控制便是其中之一,它適合于這種情況:假定并發(fā)沖突只是偶爾發(fā)生,絕大多數(shù)的時候并不會出現(xiàn)。 當(dāng)發(fā)生一個沖突時,僅僅簡單的告知用戶,他所作的更改不能保存,因為別的用戶已經(jīng)修改了同一條記錄。注意:對應(yīng)用程序來說,假定并發(fā)沖突經(jīng)常發(fā)生,且無法容忍。在這種情況下最后用保守式并發(fā)控制。關(guān)于保守式并發(fā)控制的更多討論,請參考Implementing Optimistic Concurrency 教程。開放式并發(fā)控制的作用在于:確保要更新或刪除的記錄的值與該記錄在updating or deleting階段的值相同。比如,例如,當(dāng)在一個可編輯的GridView里點擊編輯按鈕時,該記錄的原始值從數(shù)據(jù)庫中讀取出來并顯示在TextBox和其他Web控件中。這些原始的值保存在GridView里。隨后,當(dāng)用戶完成他的修改并點擊更新按鈕,這些原始值加上修改后的新值發(fā)送到業(yè)務(wù)邏輯層,然后到數(shù)據(jù)訪問層。數(shù)據(jù)訪問層必定發(fā)出一個SQL語句,它將僅僅更新那些開始編輯時的原始值根數(shù)據(jù)庫中的值一致的記錄。圖3描述了這些事件發(fā)生的順序。圖3:為了更新或刪除能夠成功,原始值必須與數(shù)據(jù)庫中相應(yīng)的值一致有多種方法可以實現(xiàn)開放式并發(fā)控制(查看Peter A. Bromberg的文章 Optmistic Concurrency Updating Logic,從摘要中看到許多選擇)。SqlDataSource控件使用該方法(就像數(shù)據(jù)訪問層中ADO.NET類型的數(shù)據(jù)集使用的那樣)擴(kuò)展WHERE字句,用以包含用來做比較的原始值。例如下面的UPDATE語句,當(dāng)當(dāng)前數(shù)據(jù)庫中的值與GridView中開始編輯的原始值一致才更新某個產(chǎn)品的名稱和價格。ProductName 和 UnitPrice參數(shù)包含的是用戶輸入的新值,而參數(shù)original_ProductName 和 original_UnitPrice則包含最初點擊編輯按鈕時加載到GridView中的值:?1234567UPDATE Products SETProductName = ProductName,UnitPrice = UnitPriceWHEREProductID = original_ProductID ANDProductName = original_ProductName ANDUnitPrice = original_UnitPrice就像我們將在本教程看到的一樣,使SqlDataSource能實現(xiàn)開放式并發(fā)控制是很簡單的事情。第一步:創(chuàng)建一個支持開放式并發(fā)的SqlDataSource控件打開SqlDataSource文件夾中的OptimisticConcurrency.aspx頁面,從工具箱拖一個SqlDataSource控件到頁面,設(shè)置其ID為ProductsDataSourceWithOptimisticConcurrency。在其智能標(biāo)簽里點“設(shè)置數(shù)據(jù)源”,數(shù)據(jù)庫選為“NORTHWINDConnectionString”,點下一步。圖4:選“ORTHWINDConnectionString”數(shù)據(jù)庫在此例子里,我們將添加一個GridView控件以編輯表Products。所以在“Configure the Select Statement”界面選擇從表Products返回ProductID, ProductName, UnitPrice和Discontinued列,如圖5所示:圖5:從表Products返回ProductID, ProductName, UnitPrice和Discontinued列然后,點“高級”按鈕,打開“Advanced SQL Generation Options”對話框,選擇“Generate INSERT, UPDATE, and DELETE statements”和“Use optimistic concurrency”2項,點“OK”(見圖1)。再點下一步、完成,結(jié)束設(shè)置。完成設(shè)置數(shù)據(jù)源向?qū)Ш?,花幾分鐘查看DeleteCommand和UpdateCommand屬性,以及DeleteParameters和UpdateParameters標(biāo)簽。最快的方法是切換到“源模式”直接在頁面代碼查看,你會看到UpdateCommand的值像這樣:?123456789UPDATE Products SETProductName = ProductName,UnitPrice = UnitPrice,Discontinued = DiscontinuedWHEREProductID = original_ProductID ANDProductName = original_ProductName ANDUnitPrice = original_UnitPrice ANDDiscontinued = original_Discontinued同時在標(biāo)簽里有7個參數(shù):?12345678910111213141516.同樣的,DeleteCommand屬性和標(biāo)簽如下:?123456DELETE FROM ProductsWHEREProductID = original_ProductID ANDProductName = original_ProductName ANDUnitPrice = original_UnitPrice ANDDiscontinued = original_Discontinued?12345678910111213.選擇了“Use optimistic concurrency”選項后,不僅擴(kuò)展了UpdateCommand 和DeleteCommand屬性里的WHERE字句(同時在相關(guān)參數(shù)集里添加了參數(shù)),同時調(diào)整了以下2個屬性:1. 將ConflictDetection屬性由“OverwriteChanges”(默認(rèn)值)改為 “CompareAllValues ”2. 將OldValuesParameterFormatString屬性由“0”(默認(rèn)值)改為 “original_0”當(dāng)數(shù)據(jù)Web控件調(diào)用SqlDataSource的Update()或Delete()方法時,它將傳遞原始值。當(dāng)SqlDataSource的ConflictDetection屬性設(shè)置為“CompareAllValues”時,就會將這些原始值添加到命令中。而OldValuesParameterFormatString屬性則為這些原始值提供了命名規(guī)范,向?qū)б浴皁riginal_0”的形式為 UpdateCommand和DeleteCommand中的原始值以及和中的參數(shù)命名。注意:由于我們沒有使用SqlDataSource控件的插入功能,因此可以將InsertCommand 屬性和標(biāo)簽清除。正確地處理NULL值不幸的是,當(dāng)使用開放式并發(fā)的時候,由設(shè)置數(shù)據(jù)源向?qū)ё詣由傻摹U(kuò)展成包含WHERE字句的UPDATE和 DELETE命令不能處理那些含有NULL值的記錄。為什么呢?先看SqlDataSource的UpdateCommand語句:?123456789UPDATE Products SETProductName = ProductName,UnitPrice = UnitPrice,Discontinued = DiscontinuedWHEREProductID = original_ProductID ANDProductName = original_ProductName ANDUnitPrice = original_UnitPrice ANDDiscontinued = original_Discontinued表Products的UnitPrice列的值允許為NULL,如何某條記錄的UnitPrice確實為NULL,那么WHERE字句的“UnitPrice = original_UnitPrice”總是為False,NULL = NULL總是返回False。所以凡是y包含NULL值的記錄不能被編輯或刪除,因為UPDATE和DELETE命令中的WHERE字句不能返回記錄。注意:這個漏洞最早于2004年6月報告給微軟,據(jù)業(yè)內(nèi)傳言,微軟將在ASP.NET的下一個版本修補該漏洞。為修補該漏洞,我們需要在UpdateCommand和DeleteCommand屬性里手工修改所有允許為NULL值的列。一般來說,將ColumnName = original_ColumnName to改成:?12345(ColumnName IS NULL AND original_ColumnName IS NULL)OR(ColumnName = original_ColumnName)你可以在屬性窗口的UpdateQuery或DeleteQuery選項的代碼聲明里修改,或者在設(shè)置數(shù)據(jù)源向?qū)У摹爸付ㄗ远xSQL語句或存儲過程”選項的“更新”和“刪除”標(biāo)簽里修改。確保在UpdateCommand和DeleteCommand的WHERE字句里做相同的修改。如下:?1234567891011121314151617UPDATE Products SETProductName = ProductName,UnitPrice = UnitPrice,Discontinued = DiscontinuedWHEREProductID = original_ProductID ANDProductName = original_ProductName AND(UnitPrice IS NULL AND original_UnitPrice IS NULL)OR (UnitPrice = original_UnitPrice) ANDDiscontinued = original_DiscontinuedDELETE FROM ProductsWHEREProductID = original_ProductID ANDProductName = original_ProductName AND(UnitPrice IS NULL AND original_UnitPrice IS NULL)OR (UnitPrice = original_UnitPrice) ANDDiscontinued = original_Discontinued第2步:為GridView控件添加編輯和刪除項當(dāng)設(shè)置SqlDataSource控件支持開放式并發(fā)時,我們需要在頁面上添加一個數(shù)據(jù)Web控件,以便執(zhí)行開放式并發(fā)控制。本章我們添加一個提供編輯和刪除功能的GridView控件。從工具箱拖一個GridView到頁面上,設(shè)置其ID為Products,并綁定到第一步添加的SqlDataSource控件ProductsDataSourceWithOptimisticConcurrency,最后啟用其“編輯”和“刪除”功能。圖6:將GridView綁定到SqlDataSource并啟用編輯和刪除功能添加GridView控件后,優(yōu)化其界面。將ProductID列移除;將ProductName列的HeaderText屬性設(shè)置為“Product”;同樣,UnitPrice列的設(shè)置為“Price”。另外,我們最好為ProductName添加一個RequiredFieldValidator控件;為UnitPrice添加一個CompareValidator控件(確保其為格式化的數(shù)字值)。參考教程Customizing the Data Modification Interface看如何自定義GridView界面。注意:必須確保激活GridView控件的view state(視圖狀態(tài)),因為GridView控件傳遞原始值時,將原始值保存在view state中。對GridView控件做了這些修改后,GridView控件和SqlDataSource控件的聲明代碼看起來和下面的差不多:?1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253asp:SqlDataSource ID=ProductsDataSourceWithOptimisticConcurrencyrunat=server ConflictDetection=CompareAllValuesConnectionString=DeleteCommand=DELETE FROM ProductsWHERE ProductID = original_ProductIDAND ProductName = original_ProductNameAND (UnitPrice IS NULL AND original_UnitPrice IS NULL)OR (UnitPrice = original_UnitPrice)AND Discontinued = original_DiscontinuedOldValuesParameterFormatString=original_0SelectCommand=SELECT ProductID, ProductName, UnitPrice, DiscontinuedFROM ProductsUpdateCommand=UPDATE ProductsSET ProductName = ProductName, UnitPrice = UnitPrice,Discontinued = DiscontinuedWHERE ProductID = original_ProductIDAND ProductName = original_ProductNameAND (UnitPrice IS NULL AND original_UnitPrice IS NULL)OR (UnitPrice = original_UnitPrice)AND Discontinued = original_Discontinued來實際地感受一下開放式并發(fā)控制。在2個瀏覽器里同時打開OptimisticConcurrency.aspx頁面,且都點擊第一條記錄的編輯按鈕。在第一個瀏覽器里改變產(chǎn)品名稱并點“編輯”。瀏覽器將發(fā)生回傳,GridView控件又回到“預(yù)編輯”狀態(tài),顯示新的產(chǎn)品名稱。在第2個瀏覽器里,改變產(chǎn)品的價格(不要改產(chǎn)品名稱)后,點“編輯”。發(fā)生回傳,GridView控件又回到“預(yù)編輯”狀態(tài),和第1個瀏覽器顯示的結(jié)果一樣產(chǎn)品的名稱改變了但價格沒改變,第2個瀏覽器做的修改失敗了。然而,一切都發(fā)生的那么靜悄悄,沒有任何提示剛才發(fā)生了并發(fā)沖突!圖7:第2個瀏覽器所做的修改悄悄的丟失了第2個瀏覽器更新失敗的原因在于:UPDATE命令中WHERE字句過濾掉了所以的記錄,沒有影響到任何一行記錄(即沒找到滿足條件的記錄)。我們再來看UPDATE 語句:?12345678910UPDATE Products SETProductName = ProductName,UnitPrice = UnitPrice,Discontinued = DiscontinuedWHEREProductID = original_ProductID ANDProductName = original_ProductName AND(UnitPrice IS NULL AND original_UnitPrice IS NULL) OR(UnitPrice = original_UnitPrice) ANDDiscontinued = original_Discontinued當(dāng)?shù)?個瀏覽器更新記錄時,WHERE字句里的原始產(chǎn)品名(即Chai)與當(dāng)前任意一條記錄的產(chǎn)品名不匹配(因為第1個瀏覽器將Chai改為了Chai Tea)。所以表達(dá)式“ProductName = original_ProductName ”返回False,導(dǎo)致更新失敗。注意:刪除的原理于此相同。同時打開2個瀏覽器,第1個先對某個產(chǎn)品作更改,再在第2個瀏覽器刪除該產(chǎn)品,同樣是因為原始值與更新后的值不匹配,刪除失敗。在最終用戶(更新失敗的那個)看來,他點“更新”按鈕后,GridView控件返回“預(yù)編輯”狀態(tài),但提交的修改丟失了。然而沒有任何直觀的提醒表明修改失敗。當(dāng)用戶的更新因并發(fā)沖突失敗時,我們最好提醒用戶,比如將GridView控件保持在“編輯”狀態(tài)。下面我們來看如何實現(xiàn)這一點。第3步:并發(fā)沖突的處理因為并發(fā)沖突拒絕用戶的更改,所以當(dāng)發(fā)生并發(fā)沖突時最好提示用戶。在頁面上添加一個Label控件,其ID為ConcurrencyViolationMessage,設(shè)置其Text 屬性為“You have attempted to update or delete a record that was simultaneously updated by another user. Please review the other users changes and then redo your update or delete”,設(shè)置其CssClass屬性為“Warning”,它定義在Styles.css中。最后,把Visible和EnableViewState屬性設(shè)置為“false” 。這樣Label控件將不可見,除非發(fā)生了某些回傳事件(我們在這些回傳事件里指定Label控件的Visible屬性為true)圖8:在頁面添加一個Label控件用以顯示提醒信息執(zhí)行更新或刪除操作時,當(dāng)GridView的數(shù)據(jù)源控件完成更新或刪除后,才開始執(zhí)行GridView控件的RowUpdated和RowDeleted事件處理器(event handler)。我們可以在這些事件處理器里計算影響了多少條記錄。假如影響了0條記錄,亦即操作失敗,我們希望將Label控件ConcurrencyViolationMessage顯示出來。為Row

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論