数据库-ADONET-在数据集DataSet中使用关系对象DataRelation处理关系
處理關系數據
數據庫中,表很少是獨立結構的,大部分數據庫都包含相互關聯的表。
在構建應用程序時,會遇到——顯示或者通過程序設計訪問數據庫中相關表的數據的情況。
用戶會希望,能通過在不同的表之間定位,來方便的找到相關的行;當父行被修改時,會希望改動可以向下級聯到子行上去。
1????????? 關系數據訪問——概述
ADONET不是關系數據訪問的先驅。
首先回顧一下處理相關表數據的常見方法
1.1???????? 聯合查詢(Join查詢)
Join查詢要早于所有的Microsoft數據訪問技術。
它是——以單個查詢獲取多個表中數據的簡單、標準的方法。
舉例如下:
Select c.CustomerID,c.CompanyName,c.ContactName,c.Phone,o.OrderID,o.EmployeeID,
o.OrderDate,d.ProductID,d.Quantity,d.UnitPrice
from Customers c, Orders o, [Order Details] d
Wherr c.CustomerID=o.CustomerID and o.OrderID=d.OrderID
Join查詢的好處:
l?是被廣泛接受的標準
l?它將結果返回到一個單獨的結構中
l?很容易篩選
Join查詢的缺點:
l?會返回冗余數據。假如客戶有100個訂單,它會將客戶信息返回到每個訂單上
l?難于更新。
l?難于同步。
1.2???????? 單獨查詢
使用單獨查詢獲取各表中的數據,并形成單獨的結構。
好處:
l?比聯合查詢返回的數據總量少
l?更適合更新
l?適合多個數據源
缺點:
l?需要同步代碼
l?難于篩選
1.3???????? 層次化的ADO Recordset對象
ADO 2.0引入了層次化的Recordset的概念。
使用特殊的提供程序和專門的查詢語法將多個查詢的結果組合到一個結構中。
示例:將獲取的Customers、 Orders、 Order Details表中的內容存放到一個層次化Recordset中。
Dim rsCustomers as ADODB.Recordset, rsOrders As ADODB.Recorders
Dim rsOrderDetails As ADODB.Recordset
Dim strConn As String, strSQL as String
strConn=”Provider=MSDataShape;Data Provider=SQLOLEDB; Data Source={local}"NetSDK; Initial Catalog=Northwind; Trusted_Connection=Yes;”
strSql=”SHAPE {select CustomerID,CompanyName,ContactName,ContactTitle from Customers} AS
?Customers APPEND ({SHAPE {select OrderID,CustomerID,EmployeeID,OrderDate from Orders } AS Orders APPEND ({select OrderID,ProductID,UnitPrice,Quantity from [Order Details]} AS OrderDetails RELATE ‘OrderID’ TO ‘OrderID’) AS OrderDetails) AS Orders RELATE ‘CustomerID’ TO ‘CustomerID’ ) AS Orders”
Set rsCustomers=New ADODB.Recordset
rsCustomers.Open strSQL,strConn,adOpenStatic,adLockBatchOptimistic
Set rsOrders=rsCustomers.Fields(“Orders”).Value
Set rsOrderDetails=rsOrders.Fields(“OrderDetails”).Value
這里有3個Recordset對象,它們都引用了一個結構中的數據。對最高級別的Recordset進行定位時,子Recordset對象中只有相關的數據才是可見的。
l?優點:
1.??????? 比Join查詢返回的數據總量小
2.??????? 返回的數據在一個單獨的結構中
3.??????? 不需要復雜的同步代碼
4.??????? 適合簡單的更新
l?缺點:
1.??????? 查詢語句難于使用(SHAPE語法)
2.??????? 提供的控制能力有限
3.??????? 只能查詢單獨的數據源
4.??????? 難于篩選
1.4???????? ADONET的DataRelation對象
DataRelation對象不需要額外的提供程序,而且不需要難于使用的SHAPE查詢。
DataRelation對象屬于DataSet對象架構的一部分。
DataRelation結合了——單獨查詢和層次化的Recordset方法的最好功能——以管理來自相關表的數據,并幾乎克服了它們的所有缺點。
l?好處:
1.??????? 比Join查詢返回的數據少
2.??????? 簡化了相關數據的定位
3.??????? 不需要復雜的同步代碼
4.??????? 可以處理復雜的更新(例如:在提交新訂單之前提交新的客戶,同時還可以在刪除現有客戶之前先刪除現有訂單。而且,如果有一系列未提交的訂單和訂單細節,可以在提交新訂單細節之前,提取服務器為新訂單所產生的自動遞增值。)
5.??????? 它們是動態的(在查詢相關數據庫表之前或之后,通過程序設計來創建、修改和刪除DataRelation對象)
6.??????? 支持層疊改變(可以通過用與DataRelation相關聯的ForeignkeyConstraint屬性來空值是否對——一行所做的改動層疊到子行上去。)
7.??????? 支持從不同的數據源創建層次結構
l?缺點
1.??????? 難于篩選(DataRelation對象不是只提取這種子行)
2????????? 在代碼中使用DataRelation對象
盡管可以純粹的編寫代碼來對多個表中的數據進行(定位、驗證、匯總、級聯更改),但是使用ADONET的DataRelation對象,可以迅速和簡單的實現這些功能。
2.1???????? 創建DataRelation對象
DataRelation對象有幾個重要的屬性,你可以在構造函數中設置它們。
l?提供一個名稱,以便在集合中定位對象
l?指定基于該關系的父列和子列
n?可以接受單個的DataColumn對象
n?也可以接受DataColumn數組
l?代碼示例
??????? Dim rel As DataRelation
??????? rel = New DataRelation("訂單關系", DataSet1.Tables("訂單").Columns("訂單ID"), DataSet1.Tables("訂單明細").Columns("訂單ID"))
??????? DataSet1.Relations.Add(rel)
如果希望定義基于多列的關系,那么可以使用接受DataColumn對象數組的構造函數。
DataRelation的兩個特別構造函數,公開了第四個參數(用來知名是否創建約束——以增強基于新關系的引用完整性)。默認時,創建新DataRelation對象,如果沒有約束,會向DataTable中添加約束。
創建的新DataRelation對象,應該添加到DataSet對象的Relations集合。
2.2???????? 查找關系數據
DataRelation對象的主要用途就是,在不同的DataTable對象中查找關系數據。
但是,DataRelation不處理這個任務,或者說不直接處理。
這個功能實際上是通過DataRow對象的GetChileRows、GetParentRow、GetParentRows方法提供的。
在調用以上DataRow對象方法時,要指定一個DataRelation參數
2.2.1?? DataRow對象的GetChildRows方法
該方法用于查找一個與另一個DataTable的子行相關聯的行。
使用該方法,需要調用DataRow對象的GetChildRows,并提供定義了DataTable對象之間關系的DataRelation對象的名稱(或者直接提供對象)
該方法的返回值,返回關系型數據(DataRow對象的一個數組)
2.2.2?? DataRow對象的GetParentRow方法
DataRelation對象,不僅可以在層次結構中由上至下搜索,還可以由下至上。
DataRow對象的GetParentRow方法,根據DataSet對象中的DataRelation對象來查找父行。
該方法,需要DataRelation對象作參數,或者是,包含DataRelation對象名字的字符串。
2.2.3?? DataRow對象的GetParentRows方法(注意,有個復數s)
如果處理的是一種多對多的關系,并且希望檢查特定DataRow的所有父行,那么就可以使用DataRow對象的GetParentRows方法了。
此方法與上面的方法簽名式相同
2.2.4?? 選擇要查看的數據版本
假設:已經構建了一個讓用戶從數據庫中返回數據并修改該數據的應用程序。
但是使用這個應用程序的員工并不是非常可靠的。他們會犯錯誤。
所以應用程序使用看一些DataSet公開的功能,將所做的改動存儲到一個文件中,而不是提交給數據庫。
因此,必須創建第二個應用程序,以便讓管理員檢查員工使用程序#1輸入的掛起更改,這個審核程序能同時顯示DataSet中修改行的原始值和修改后的值。
?
我們可以用DataRow對象的Item屬性檢查行中特定列的原始值和當前值。
另外,DataRow對象的GetChildRows、GetParentRow、GetParentRows方法,可以使用DataRowVersion類型枚舉值作參數,來指明訪問哪個版本的數據。
2.3???????? 使用DataRelation對象驗證數據
DataRelation對象的一個主要功能就是——驗證數據(另一個主要功能是:對來自相關DataTable的數據進行定位)
在定義兩個DataTable之間的關系的時候,一般都會希望保證在子DataTable中不會出現“孤立”的數據,也就是說,希望能夠防止用戶在Orders表中輸入在Customers表中沒有對應行的那些行。
可以用DataRelation對象來增強對相關DataTable對象的約束。
2.3.1?? 創建約束
在默認情況下,創建DataRelation對象時能夠確保在父級DataTable對象上有一個惟一約束,在子DataTable上有一個外鍵約束。
l?代碼演示:(在Customers的DataTable對象的CustomerID列上創建一個惟一約束,在Orders的DataTable上CustomerID列上創建一個外鍵約束)
??????? Dim daCustomers As New OleDb.OleDbDataAdapter("select 客戶ID,公司名稱,聯系人姓名from 客戶", OleDbConnection1)
??????? Dim daOrders As New OleDb.OleDbDataAdapter("select 訂單ID,客戶ID,訂購日期from 訂單", OleDbConnection1)
?
??????? Dim ds As New DataSet
??????? daCustomers.Fill(ds, "客戶")
??????? daOrders.Fill(ds, "訂單")
?
??????? ds.Relations.Add("CustomersOrders", ds.Tables("客戶").Columns("客戶ID"), ds.Tables("訂單").Columns("客戶ID"))
?
?
??????? ListBox1.Items.Add("父表——客戶表,現在有" & ds.Tables("客戶").Constraints.Count & "個約束;它叫做:" & ds.Tables("客戶").Constraints(0).ConstraintName)
??????? ListBox1.Items.Add("子表——訂單表,現在有" & ds.Tables("訂單").Constraints.Count & "個約束;它叫做:" & ds.Tables("客戶").Constraints(0).ConstraintName)
?
2.3.2?? 使用現有約束
還可以事先定義出自己的約束。
新的DataRelation將使用現有的約束而不是創建新的約束。
??????? '首先給客戶表定義主鍵
??????? With ds.tables("客戶")
??????????? .PrimaryKey = New DataColumn() {.Columns("客戶ID")}
??????? End With
??????? '然后給訂單表定義外鍵
??????? With ds.Tables("訂單")
??????????? '.Constraints.Add("FK_CustomersOrders", ds.Tables("客戶").Columns("客戶ID"), .Columns("客戶ID"))
??????????? .Constraints.Add(New ForeignKeyConstraint("kd", ds.Tables("客戶").Columns("客戶ID"), .Columns("客戶ID")))
??????? End With
??????? '現在添加關系
??????? ds.Relations.Add("co", ds.Tables("客戶").Columns("客戶ID"), ds.Tables("訂單").Columns("客戶ID"))
?
??????? '現在顯示
??????? ListBox1.Items.Add("父表- " & ds.Tables("客戶").TableName & "現在有" & ds.Tables("客戶").Constraints.Count & "個約束")
2?外鍵約束和空值
此處可能引起你懷疑的是——為什么即使在定義了外鍵約束的情況下,還是可能在數據庫和DataSet中出現“孤立”的數據?????
難道你不相信可以對Northwind數據庫運行下面的查詢?
Update Orders SET CustomerID=NULL where CustomerID=”ALFKI”
這個查詢會成功執行,這樣,Orders表中就會出現不屬于Customers表的客戶訂單了。
要把行設置為Customers表的恰當客戶,你可以:
Update Orders SET CustomerID=’ALFKI’ where CustomerID is NULL
為了證明在Orders表中有外鍵約束,可以運行下面的查詢
Update Orders SET customerID=’ZZZZZ’ where CustomerID=’ANTON’
如果Customers表中沒有CustomerID=’ZZZZZ’的行,查詢會失敗。
在定義數據庫和DataSet時要記住:在外鍵約束中至少有一列包含NULL值的行,是不受約束限制的。
2.3.3?? 看,約束沒了!
已知,在創建DataRelation時,ADONET默認會保證給DataSet包含——(其簽名與新DataRelation一致的)惟一鍵UniqueConstraint和外鍵ForeignKeyConstraint。
而且,如果DataSet中歐冠呢已經有這種約束,新的DataRelation會自動引用它們。
否則,ADONET將會隱式地創建新的約束。
不過,你也可以指定ADONET不為DataRelation創建約束。當你希望使用DataRelation,但不想在DataSet中有相應約束時,你可以在DataRelation類的某些構造函數中指定參數(布爾型參數createConstraints)。
2.4???????? 自引用DataRelationShip對象
有時關系中的父表和子表是同一個表。
比如:對于Northwind數據庫中的Employees表。這個表中有一個包含員工ID的列,和一個包含員工管理者ID的列(ReportsTo)。員工表還有一個在ReportsTo列上定義的外鍵約束用來確保它只能接受來自EmployeeID列的值。
??????? '首先取員工表
??????? Dim da As New OleDb.OleDbDataAdapter("select 雇員ID,姓氏+名字as 姓名, 上級from 雇員", OleDbConnection1)
??????? da.Fill(ds, "雇員")
?
??????? '給雇員表添加自引用
??????? Dim tbl As DataTable = ds.Tables("雇員")
??????? 'ds.Relations.Add("SelfReferentcing", tbl.Columns("雇員ID"), tbl.Columns("上級"), False)
??????? ds.Relations.Add(New DataRelation("selfr", tbl.Columns("雇員ID"), tbl.Columns("上級"), False))
2.5???????? 多對多關系
大部分數據庫——關系都是一對多的。
但是,多對多的關系確實存在。比如:SQL Server中的pubs數據庫,其中的authors和titles表,這兩個表中的數據關系可以認為是多對多的,因為一個作者可以寫很多書,而一部書可以有多位作者。然而,由于“外鍵約束需要一個惟一鍵”,所以這兩個表并不是直接通過外鍵約束相關聯的。這樣可以防止子行在相關表中有多個父行。既是意味著沒有直接的多對多關系。
Pubs數據庫包括的另外一個名叫titleauthor的表,這個表用來創建非直接多對多關系的表。它有一個復合主鍵,這個復合主鍵有au_id和title_id組成,分別對應authors和titles表的主鍵。
假設一個作品有兩位作者,titleauthors表就會包括該作品的兩個作者行。
因此,可以用titleauthors表找到特定作品的所有合著作者;或者利用這個表,找到特定作者寫過的或合寫的所有作品的主鍵值。
下面的代碼演示:從這三個表中獲取數據。在作者表和關系表、作品表和關系表——之間添加關系DataRelation對象,然后根據關系,循環查找作者表中的行,顯示每一位作者(對于每個作者,取關系表中的子行,每個子行再反向從作品表中取父行,從而得到每個作者的作品列表)
??????? Dim da As SqlClient.SqlDataAdapter
??????? '先取作者表數據
??????? da = New SqlClient.SqlDataAdapter("select au_id, au_lname + au_fname as name from authors", SqlConnection1)
??????? da.Fill(DataSet1, "作者")
??????? '取作品表數據
??????? da.SelectCommand = New SqlClient.SqlCommand("select title_id,title from titles", SqlConnection1)
??????? da.Fill(DataSet1, "作品")
??????? ' 取兩者的關系表
??????? da.SelectCommand = New SqlClient.SqlCommand("select au_id,title_id from titleauthor", SqlConnection1)
??????? da.Fill(DataSet1, "關系")
?
??????? '先定義作者表au_id的關系
??????? DataSet1.Relations.Add("authors_titleauthors", DataSet1.Tables("作者").Columns("au_id"), DataSet1.Tables("關系").Columns("au_id"), False)
??????? '在定義作品表的title_id的關系
??????? DataSet1.Relations.Add("titles_titleauthors", DataSet1.Tables("作品").Columns("title_id"), DataSet1.Tables("關系").Columns("title_id"), False)
?
??????? '下面代碼,用來顯示效果
??????? Dim row_author, row_title, row_titleauthors As DataRow
??????? For Each row_author In DataSet1.Tables("作者").Rows
??????????? ListBox1.Items.Add(row_author("name"))
??????????? For Each row_titleauthors In row_author.GetChildRows("authors_titleauthors")
??????????????? row_title = row_titleauthors.GetParentRow("titles_titleauthors")
??????????????? ListBox1.Items.Add(vbTab & "《" & row_title("title") & "》")
??????????? Next
?
??????? Next
2.6???????? 在基于表達式的數據列DataColumns對象中使用關系對象DataRelation
你可以用DataColumn對象的Expression屬性,創建并顯示表達式;
還可以將基于表達式的DataColumn對象與DataRelation對象結合,用來計算匯總的信息。(例如:子行數和子數據的總和與平均值)
l?代碼演示?
??????? '首先在數據集里面收集訂單和訂單明細表的數據
??????? Dim da As New OleDb.OleDbDataAdapter("select * from 訂單", dc)
??????? da.Fill(ds, "訂單")
??????? da.SelectCommand = New OleDb.OleDbCommand("select * from?訂單明細", dc)
??????? da.Fill(ds, "訂單明細")
?
??????? '增加兩表中訂單ID的關系
??????? Dim tblOrders, tblOrderDetails As DataTable
??????? tblOrderDetails = ds.Tables("訂單明細")
??????? tblOrders = ds.Tables("訂單")
??????? ds.Relations.Add("訂單標識關系", tblOrders.Columns("訂單ID"), tblOrderDetails.Columns("訂單ID"))
?
??????? '現在添加單項總價數據列-放在明細表
??????? tblOrderDetails.Columns.Add("單項總價", GetType(Decimal), "單價* 數量* (1- 折扣)")
??????? ' 在訂單表添加數據列-用來保存子行數
??????? tblOrders.Columns.Add("子行數", GetType(Integer), "Count(Child.產品ID)")
??????? '在訂單表添加此單總價列
??????? tblOrders.Columns.Add("此單總價", GetType(Decimal), "Sum(Child.單項總價) + 運貨費")
程序說明:首先,創建起訂單表和訂單明細表直接的關系,然后將單項總價列添加到訂單明細表,將子行數和此單總價列添加到訂單表。
返回子行數量,要設置數據列對象的Expression屬性為:Count(Child.產品ID)
注意這種語法適合數據表只有一個相關子表對象的情況;如果父表有多個相關的子表,需要的語法是:Count(Child(RelationName).產品ID)
最好,在訂單表中添加列,用來計算總價:Sum(Child.單項總價)
?
DataColumn.Expression屬性——引用
用來計算列的值,或創建聚合列的表達式。表達式的返回類型由列的 DataType 來確定。
Expression 屬性的一個用途是創建計算出的列。例如,若要計算稅值,就要將單價乘以特定地區的稅率。由于各地稅率不同,不可能將單一稅率放在一個列中;于是便用 Expression 屬性來計算這個值,如下面這一部分中的 Visual Basic 代碼所示:
DataSet1.Tables("Products").Columns("tax").Expression = "UnitPrice * 0.086"
第二個用途是創建聚合列。類似于計算出的值,聚合基于 DataTable 中的整個行集執行操作。一個簡單的示例就是計算該集中返回的行數。這便是您將用來計算特定銷售人員所完成的交易數的方法
表達式語法
在創建表達式時,使用 ColumnName 屬性來引用列。例如,如果一個列的 ColumnName 是“UnitPrice”,而另一個是“Quantity”,則表達式將是:
"UnitPrice * Quantity"
| 注意 |
| 如果在表達式中使用了某個列,則該表達式就存在一個對該列的依賴項。重命名或移除依賴列時不會引發異常。當訪問缺少了依賴項的表達式列時,將引發異常。 |
在為篩選器創建表達式時,用單引號將字符串括起來:
"LastName = 'Jones'"
下面的字符是特殊字符,如下面所解釋的,如果它們用于列名稱中,就必須進行轉義:
"n (newline)
"t (tab)
"r (carriage return)
~
(
)
#
"
/
=
>
<
+
-
*
%
&
|
^
'
"
[
]
如果列名稱包含上面的字符之一,該名稱必須用中括號括起來。例如,若要在表達式中使用名為“Column#”的列,應寫成“[Column#]”:
Total * [Column#]
由于中括號是特殊字符,如果它是列名稱的組成部分,必須使用斜杠 (""") 將中括號轉義。例如,名為“Column[]”的列應寫成:
Total * [Column["]]
(只有第二個中括號必須轉義。)
用戶定義的值
用戶定義的值可以用在將與列值進行比較的表達式內。字符串的值應括在單引號內。日期值應放在磅符號 (#) 內。對于數值,允許使用小數和科學記數法。例如:
"FirstName = 'John'"
"Price <= 50.00"
"Birthdate < #1/31/82#"
對于包含枚舉值的列,將值強制轉換為整數數據類型。例如:
"EnumColumn = 5"
運算符
使用布爾值 AND、OR 和 NOT 運算符時允許串聯。可以使用括號來組合子句和強制優先級。AND 運算符優先于其他運算符。例如:
(LastName = 'Smith' OR LastName = 'Jones') AND FirstName = 'John'
在創建比較表達式時,允許使用下列運算符:
<
>
<=
>=
<>
=
IN
LIKE
在表達式中還支持下列算術運算符:
+(加)
-(減)
*(乘)
/(除)
%(模數)
字符串運算符
若要連接字符串,請使用 + 字符。DataSet 類的 CaseSensitive 屬性的值確定字符串比較是否區分大小寫。但是,可以用 DataTable 類的 CaseSensitive 屬性重寫該值。
通配符
在 LIKE 比較中,* 和 % 兩者可以互換地作為通配符。如果 LIKE 子句中的字符串包含 * 或 %,那么這些字符應用中括號([])對其進行轉義。如果子句中有中括號,那么中括號字符應用中括號對其進行轉義(例如 [[] 或 []])。在模式的開頭和結尾,或者在模式的結尾,或在模式的開頭,都允許使用通配符。例如:
"ItemName LIKE '*product*'"
"ItemName LIKE '*product'"
"ItemName LIKE 'product*'"
在字符串的中間不允許使用通配符。例如,不允許 'te*xt'。
父/子關系引用
通過在列名稱前面加 Parent,就可以在表達式中引用父表。例如,Parent.Price 引用父表的名為 Price 的列。
通過在列名稱前面加一個 Child,就可以在表達式中引用子表中的列。但是,因為子關系可以返回多行,所以必須在聚合函數中包括對子列的引用。例如,Sum(Child.Price) 將返回子表中名為 Price 的列的總和。
如果某個表有多個子表,則語法是:Child(RelationName)。例如,如果某個表有兩個子表,它們的名稱分別為 Customers 和 Orders,并且 DataRelation 對象被命名為 Customers2Orders,則引用將為:
Avg(Child(Customers2Orders).Quantity)
聚合
支持下列聚合類型:
Sum(求和)
Avg(平均)
Min(最小值)
Max(最大值)
Count(計數)
StDev(統計標準偏差)
Var(統計方差)。
聚合通常沿著關系執行。通過使用上面列出的函數之一和上面“父/子關系引用”中詳述的子表列,來創建聚合表達式。例如:
Avg(Child.Price)
Avg(Child(Orders2Details).Price)
聚合也可以在單個表上執行。例如,若要為名為“Price”的列中的數字創建匯總,就用:
Sum(Price)
| 注意 |
| 如果使用一個表來創建聚合,將沒有組合功能。相反,所有行都在列中顯示相同的值。 |
如果表沒有行,聚合函數將返回空引用(在 Visual Basic 中為 Nothing)。
數據類型總是可以通過檢查列的 DataType 屬性來確定。還可以使用 Convert 函數來轉換數據類型,如下面這一部分所示。
FUNCTIONS
還支持下列函數:
CONVERT
| 說明 | 將特定表達式轉換為指定的 .NET Framework 類型。 |
| 語法 | Convert(expression, type) |
| 參數 | expression — 要轉換的表達式。 type — 值將轉換成的 .NET Framework 類型。 |
例如:myDataColumn.Expression="Convert(total, 'System.Int32')"
所有轉換都是有效的,只有下列情況例外:Boolean 只能與 Byte、SByte、Int16、Int32、Int64、UInt16、UInt32、UInt64、String 和它本身相互轉換。Char 只能與 Int32、UInt32、String 和它本身相互轉換。DateTime 只能與 String 和它本身相互轉換。TimeSpan 只能與 String 和它本身相互轉換。
LEN
| 說明 | 獲取字符串的長度 |
| 語法 | LEN(expression) |
| 參數 | expression — 要計算的字符串。 |
例如:myDataColumn.Expression="Len(ItemName)"
ISNULL
| 說明 | 檢查表達式并返回已檢查的表達式或返回替換值。 |
| 語法 | ISNULL(expression, replacementvalue) |
| 參數 | expression — 要檢查的表達式。 replacementvalue — 如果表達式為 空引用(在 Visual Basic 中為 Nothing),則返回 replacementvalue。 |
例如:myDataColumn.Expression="IsNull(price, -1)"
IIF
| 說明 | 根據邏輯表達式的結果,獲取兩個值之一。 |
| 語法 | IIF(expr, truepart, falsepart) |
| 參數 | expr — 要計算的表達式。 truepart — 表達式為真時返回的值。 falsepart — 表達式為假時返回的值。 |
例如:myDataColumn.Expression = "IIF(total>1000, 'expensive', 'dear')
TRIM
| 說明 | 移除所有前導的和后綴的空格字符,如 "r、"n、"t、' ' |
| 語法 | TRIM(expression) |
| 參數 | expression — 要剪裁的表達式。 |
SUBSTRING
| 說明 | 獲取從字符串中的指定點開始,具有指定長度的子字符串。 |
| 語法 | SUBSTRING(expression, start, length) |
| 參數 | expression — 子字符串的源字符串。 start — 指定子字符串開始位置的整數。 length — 指定子字符串長度的整數。 |
例如:myDataColumn.Expression = "SUBSTRING(phone, 7, 8)"
| 注意 |
| 可以向 Expression 屬性分配一個空值或空字符串,來重置該屬性。如果為表達式列設置了一個默認值,則在重置 Expression 屬性之后,這個默認值就賦給所有以前填充過的行。 |
?
可以在關系中使用基于表達式的DataColumn對象,從父表對象中收集數據。
可以通過給titleauthor表對象添加基于表達式的數據列來簡化這段代碼,具體的說就是,titleauthor表通過title表使用DataRelation,來返回title表DataColumn的值。給titleauthor表添加這一列之后,就不需要通過使用GetParentRow方法在title表中查找所需的行。
2.7???????? 層疊更改
有時候,對一行所做的更改在相關的數據上會有影響,或者是(應該會有影響)。例如:刪除一個訂單,可能也想刪除與這個訂單關聯的明細行。
不同的數據庫系統,處理此種情形的方式,是不同的。
SQL SERVER中,Northwind數據列的Order Details表,使用了【外鍵約束】來防止,用戶從Orders表刪除行的情況。
SQL Server 2000引入“支持是喲個外鍵約束的層疊改變”。通過定義外鍵約束,使得用戶的更新或者刪除,會自動層疊到相關表的行上。
ADONET的ForeignKeyConstaint對象具有類似的特性,它公開了DeleteRule和UpdateRule屬性,設置這些屬性能控制,在修改外鍵約束的父表數據是,會出現什么情形。
ü?ForeignKeyConstaint對象的DeleteRule和UpdateRule屬性
DeleteRule和UpdateRule屬性接受System.Data命名空間中的Rule枚舉值。
在默認情況下,這兩個屬性值為Cascade,表示在刪除表中的行時,相關子行也會被刪除;而,如果是更新父行列值,子表對象中相關行也會更新。
這兩個屬性的可選值還有:None、SetDefault、SetNull。
若設置DeleteRule屬性=None,可以防止刪除子表對象中受影響的數據。
若希望父行更新時使子表中被約束的行為值為Null,就需要設置DeleteRule屬性=SetNull
若將屬性設置為SetDefault,則是使被約束列Default屬性被重置。
2.8???????? Join查詢
很多人依靠Join查詢,從多個表獲取數據,返回的結果可以用DataTable來存儲;
但是,一般不會建議這樣做。
因為,一般情況下,DataAdapter能夠檢查存儲在單個DataTable中的更改,并提交給數據庫指定表。
那么,如何處理Join查詢呢?
簡單的做法是,將它們分成從單獨表中返回數據的查詢。但是做起來不是很容易。
?
?
總結
以上是生活随笔為你收集整理的数据库-ADONET-在数据集DataSet中使用关系对象DataRelation处理关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广域线路打环测试步骤
- 下一篇: linux cmake编译源码,linu