前面我們提到
數據綁定控件把傳遞給數據源的值存放在相互獨立的Keys
Values(新值)和 OldValues字典中
在默認情況下
SqlDataSource和ObjectDataSource會忽略OldValues字段
只使用Keys和Values
這種行為是由數據源的ConflictDetection屬性檢測的
在默認情況下這個屬性的值被設置為OverwriteChanges
OverwriteChanges模式意味著
為了更新或刪除記錄
僅僅匹配主鍵值
這種操作意味著
記錄的更新或刪除是不考慮該記錄的下層值是否改變過了
在通常情況下
理想的狀態是
只有當數據行的值與最初選擇的值完全匹配的時候
才讓Update或Delete操作成功
在這種理想情況下
如果另外一個用戶在你選擇某一行和更新該行的之間也更新了這一行
你的更新操作就會失敗
通過把ConflictDetection屬性設置為CompareAllValues
數據源也支持這種操作
在這種模式下
數據源會把OldValues應用到命令或方法上
它會使用這些值來確保在更新或刪除記錄之前
更新或刪除操作必須與記錄的所有值都匹配
你還必須把OldValuesParameterFormatString屬性設置為一個有效的
NET框架組件格式化字符串(例如
original_{
}
)
來指明OldValues和Keys字典中的參數如何重新命名以便與NewValues參數區分開來
下面的代碼示例顯示了SqlDataSource控件在OverwriteChanges和CompareAllValues模式下使用的典型的SQL命令
ID字段被假定為主鍵字段
請注意
後面一個命令在WHERE子句中比較數據行的所有原始值
而不是僅僅比較主鍵
在這種情況下
數據源的OldValuesParameterFormatString需要被設置為
original_{
}
SELECT [ID]
[Name]
[Address] from [Contacts]
OverwriteChanges
UPDATE [Contacts] SET [Name] = @Name
[Address] = @Address WHERE [ID] = @ID
DELETE FROM [Contacts] WHERE [ID] = @ID
CompareAllValues
UPDATE [Contacts] SET [Name] = @Name
[Address] = @Address WHERE [ID] = @original_ID
AND [Name] = @original_Name AND [Address] = @original_Address
DELETE FROM [Contacts] WHERE [ID] = @original_ID AND [Name] = @original_Name
AND [Address] = @original_Address
請注意
Insert操作不需要OldValues
ConflictDetection只對Update和Delete操作有意義
下面的例子演示了沖突發生時的行為
為了運行這個例子
你必須在兩個獨立的浏覽器窗口中打開例子的兩個實例(兩次點擊
Run Sample
)
接著在兩個窗體的同一行上都點擊
Edit
按鈕
使該行進入編輯模式
在第一個窗口中改變一個值並點擊
Update
請注意這個更新是成功的
在第二個窗口中
在該行中輸入一個新值並點擊
Update
這個更新操作沒有成功
因為下層數據行的值已經被第一個更新操作改變過了
這個示例檢測了Updated或Deleted事件參數的AffectedRows屬性
它為
確認了沖突發生了
<script runat=
server
>
Protected Sub SqlDataSource
_Updated(sender As Object
e As SqlDataSourceStatusEventArgs)
If e
AffectedRows =
Then
Response
Write(
Row changed
update aborted<br />
)
End If
End Sub
Protected Sub SqlDataSource
_Deleted(sender As Object
e As SqlDataSourceStatusEventArgs)
If e
AffectedRows =
Then
Response
Write(
Row changed
delete aborted<br />
)
End If
End Sub
</script>
當Update或Delete使用模板化UI的時候
使用了Bind語法的雙向(two
way)數據綁定字段的舊值都會被保留
對於Delete來說
這意味著在ItemTemplate中你必須給數據綁定的值使用Bind語法
其目的是為了保留刪除操作所需要的舊值
下面的例子演示了這種技術
<asp:GridView ……>
<Columns>
<asp:CommandField ShowDeleteButton=
True
ShowEditButton=
True
/>
<asp:TemplateField HeaderText=
ContactID
InsertVisible=
False
SortExpression=
ContactID
>
<ItemTemplate>
<asp:Label ID=
Label
runat=
server
Text=
<%# Bind(
ContactID
) %>
></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:Label ID=
Label
runat=
server
Text=
<%# Eval(
ContactID
) %>
></asp:Label>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText=
ContactName
SortExpression=
ContactName
>
<ItemTemplate>
<asp:Label ID=
Label
runat=
server
Text=
<%# Bind(
ContactName
) %>
></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID=
TextBox
runat=
server
Text=
<%# Bind(
ContactName
) %>
></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
你可以溫和地處理沖突檢測錯誤可以通過提示用戶下層數據被改變了向用戶顯示改變過的值 讓用戶選擇提交或放棄自己的操作下面的例子演示處理沖突檢測的一種可行方法請注意DetailsView的RowUpdated事件參數傳遞了可用於檢測用戶輸入的值的字典你還可以設置這個事件參數的KeepInEditMode屬性使用戶在決定如何處理沖突期間DetailsView處於編輯模式這個例子所試驗方法與上面一個例子類似同時打開兩個窗口來創建沖突更新
Protected Sub DetailsView
_ItemUpdated(ByVal sender As Object
ByVal e As System
Web
UI
WebControls
DetailsViewUpdatedEventArgs)
If e
AffectedRows =
Then
使DetailsView處於編輯模式並與數據庫同步
e
KeepInEditMode = True
DetailsView
DataBind()
用用戶輸入的值重新填充DetailsView
Dim t As TextBox
t = DetailsView
Rows(
)
Cells(
)
Controls(
)
t
Text = e
NewValues(
OrderDate
)
t = DetailsView
Rows(
)
Cells(
)
Controls(
)
t
Text = e
NewValues(
ShipCountry
)
ErrorPanel
Visible = True
Else
ErrorPanel
Visible = False
End If
End Sub
Protected Sub DetailsView
_ModeChanging(ByVal sender As Object
ByVal e As System
Web
UI
WebControls
DetailsViewModeEventArgs)
If e
CancelingEdit = True AndAlso ErrorPanel
Visible = True Then
ErrorPanel
Visible = False
End If
End Sub
使用ObjectDataSource的時候
情況也類似
請注意
由於數據源的ConflictDetection屬性被設置為CompareAllValues
數據源將查找一個可接受Contact對象的每個字段的原始值的UpdateContact重載
你還可以同時使用DataObjectTypeName屬性和CompareAllValues
在這種情況下
ObjectDataSource查找僅接受兩個參數(都是Contact)的UpdateContact重載
第一個參數是存放新值的Contact對象
第二個參數是存放舊值的Contact對象
From:http://tw.wingwit.com/Article/program/net/201311/12138.html