转载:LINQ to SQL更新数据库操作
????? 翻譯整理ScottGu的關于LINQ to SQL的Part 4: Updating our Database 。該Post講解了如何使用LINQ to SQL更新數據庫,以及如何整合業務邏輯和自定義驗證邏輯。開發環境為.NET Framework 3.5 Beta2,開發工具為Visual Studio 2008 Beta2。?
????? 使用LINQ to SQL建模Northwind數據庫
在這之前一起學過LINQ to SQL設計器的使用,下面就使用如下的數據模型:
????? 當使用LINQ to SQL設計器設計以上定義的五個類(Product,Category,Customer,Order和OrderDetail)的時候,每個類中的屬性都映射了相應數據庫中表的列,每個類的實例則代表了數據庫表中的一條記錄。另外,當定義數據模型時,LINQ to SQL設計器同樣會創建一個自定義DataContext類,來作為數據庫查詢和應用更新/變化的主要渠道。以上數據模型中定義的DataContext類命名為“NorthwindDataContext”。該類中包含了代表每個建模數據庫表的屬性。
????? 使用LINQ語法表達式可以十分簡單的使用NorthwindDataContext類來查詢和檢索數據庫中的數據。LINQ to SQL會在運行時自動的轉換LINQ表達式到適當的SQL代碼來執行。例如,編寫以下LINQ表達式來根據Product Name檢索單個Product對象:
???? 還可以使用LINQ表達式來檢索所有不存在于Order Details中的,并且UnitPrice大于100的所以Product:
???? 變化跟蹤和DataContext.SubmitChanges()
???? 當執行查詢和檢索像Product實例這樣的對象時,LINQ to SQL會自動保持對這些對象任何變化或更新的跟蹤。我們可以進行任意次數的查詢,以及使用LINQ to SQL的DataContext類作出更新,而這些變化都會被全部跟蹤。
注意:LINQ to SQL的變化跟蹤發生于調用者端——而不是在數據庫中。這就意味著使用跟蹤不會銷耗任何數據庫資源,也不需要在數據庫中改變/安裝任何組件模塊。
當對從LINQ to SQL中檢索的對象作出更改之后,我們可以選擇調用DataContext上的SubmitChange()方法來應用變化返回到數據庫。這將會導致LINQ to SQL動態計算并執行適當的SQL代碼來更新數據庫。例如,編寫以下代碼更新數據庫中Product Name為“Chai”的Product上的UnitPrice和UnitsInStock:
當在以上代碼中調用northwind.SubmitChanges()方法時,LINQ to SQL會動態構建并執行一個更新這兩個Product屬性值的SQL“UPDATE”代碼模塊。
在下面代碼中我們來遍歷不流行的,昂貴的Product,并把它們的ReorderLevel屬性設為0:
當在以上代碼中調用northwind.SubmitChanges()方法時,LINQ to SQL會計算并執行一組適當的UPDATE代碼模塊來修改RecorderLevel屬性已變化的Product。
注意,如果一個Product的屬性沒有通過屬性指定而發生變化,則該對象不會被認為是發生變化的,并且LINQ to SQL也不會對于該對象執行更新回數據庫的操作。例如,如果“Chai”對象的UnitPrice仍舊是$2,UnitsInStock仍舊是4,當調用SubmitChange()時不會導致任何數據庫UPDATE代碼模塊的執行。相似的,在第二個例子中的那些符合條件的Product中只有RecorderLevel原來不是0的才會在SubmitChange()被調用時更新。
插入和刪除示例
除了更新數據庫中已存在的行之外,LINQ to SQL同樣支持插入和刪除數據。可以通過從DataContext的表集合中添加/移除數據對象,并調用SubmitChange()方法來實現數據庫中的插入和刪除操作。LINQ to SQL也會對添加/移除操作保持跟蹤,并當SubmitChange()被調用時自動執行適當的SQL中的INSERT或DELETE代碼模塊。
插入Product
可以通過創建一個新Product實例添加一個新的Product到數據庫,設置它的屬性,并添加它到DataContext類中的Product集合中:
當在以上代碼中調用northwind.SubmitChanges()方法時,在數據庫的Product表中會有一條新的記錄被創建。
刪除Product
與添加相似,可以通過從DataContext類中的Product集合中移除某一產品來表達想要從數據庫中刪除相應的記錄:
在以上代碼中先使用LINQ查詢檢索一系列不會被訂購的Product,然后將其傳入DataContext類中Product集合上的RemoveAll()方法。當在以上代碼中調用northwind.SubmitChanges()方法時,這些Product記錄就會從數據庫中的Product表中刪除。
通過關系關聯更新
像LINQ to SQL這樣十分靈活的O/R映射工具,可以讓我們很簡單的通過表之間的關系關聯來對數據模型建模。例如,可以把每個Product建模到一個Category中,每個Order包含多條OrderDetail明細,每條OrderDetail明細都關聯著一個Product,并且每個Customer擁有一組相關聯的Order。
LINQ to SQL能夠讓我們不論是在查詢還是更新數據中都可以利用這些關系關聯。例如,編寫以下代碼來創建一個新Product,并關聯到一個數據庫中已存在的“Beverages”Category上:
注意如何添加Product對象到該Category的Product集合中。這樣就會指明這兩個對象之間存在關系關聯,并會導致LINQ to SQL在調用SubmitChange()時,自動維護兩者之間的主/外鍵關系關聯。
另一個LINQ to SQL有助于管理交叉表關系關聯的例子,讓我們看一下如何對一個現有的Customer創建一個新的Order。在設置Order的OrderDate和RequireDate和Freight后,然后創建兩個Customer訂購的Product相關的OrderDetail,并添加到Order中,隨后關聯Order到Customer上,最后更新所有變化回數據庫:
正如所看到,執行所以這些工作的編程模型是十分清晰并且是面向對象的。
事務
事務是一種通過數據庫(或其他資源管理器)提供的服務,來保證了一系列的單獨的操作是原子性發生的——這就意味著它們要么全部成功,要么全部失敗,并且當這一系列操作都自動執行完畢之前,不會有任何更改會發生。當調用DataContext上的SumbitChange()方法時,這些更新操作會包裝到一個事務中。這就意味著當執行多個變化更新時,數據庫永遠不會陷入不一致的狀態——這些變化要么一起被保存,要么任何變化都不保存。
驗證和業務邏輯
對于處理數據,開發需要考慮的一件十分重要的事就是如何融合數據驗證和業務規則邏輯。LINQ to SQL為開發者提供了多種途徑,可以十分簡潔地把這些整合到數據模型中。LINQ to SQL會確保一旦添加數據驗證邏輯,就可以無論何時何地在都應用于數據模型上。這就避免了在多處的重復定義,保證了數據模型的可維護性和代碼整潔。
構架驗證支持
當在Visual Studio 2008中使用LINQ to SQL設計器定義數據模型類時,會被默認附加一些根據數據庫表構架推斷出的驗證規則。數據模型類中的屬性的數據類型會與數據庫構架的數據類型相匹配。這就意味著如果試圖指定一個boolean值到decimal,或試圖隱式轉換numeric類型都會導致編譯錯誤。如果數據庫中的列可以為null,則通過LINQ to SQL設計器創建的在數據模型中的相應的屬性會是一個Nullable類型。如果試圖給未標記為Nullable的屬性指定null值,會自動引發異常。相似地,LINQ to SQL也會確保數據庫中的identity/unique列值的正確驗證。
當然也可以使用LINQ to SQL設計器來覆寫這些默認的構架驅動的驗證設置——但是通過默認我們可以自動獲得它們,而且不需要進行額外的工作。LINQ to SQL同樣會自動處理轉義的SQL值,這樣就不必擔心SQL注入攻擊了。
自定義屬性驗證支持
構架驅動的數據驗證僅僅是應用的第一步,但對于實際應用來說還是不夠的。考慮Northwind中的一種情況——Customer類上的Phone屬性,在數據庫中被定義為NVARCHAR類型。開發者可以使用LINQ to SQL編寫如下代碼更新一個有效的電話號碼:
?
但在應用中會碰到這樣的疑問,如對于下面的代碼,從單純的SQL構架方面來說是合法的:
為防止虛假的電話號碼被添加進數據庫,我們可以添加一個自定義屬性驗證規則到Customer數據模型類中。使用局部類的特性,可以十分簡單的添加規則來驗證電話號碼,只需要添加一個新的包含如下方法定義的局部類到我們的項目中:
?
以上代碼利用了LINQ to SQL的兩個特性:
1.所以通過LINQ to SQL設計器創建的類都被聲明為局部類——這就意味著開發者可以十分方便地為這些類添加額外的方法,屬性和事件。這樣對通過LINQ to SQL設計器創建的數據模型類和DataContext類,可以很簡單的擴充自已定義驗證規則和額外的自定義輔助方法。沒有任何設置或后續代碼要求。
2.LINQ to SQL會在數據模型類和DataContext類中暴露了一些自定義的可擴展點,用來在事件發生之前和之后添加驗證邏輯。其中許多的擴展點利用了稱為“partial methods(局部方法)”的新語言特性。
在上面的驗證示例中,我們使用了在任何設置Customer類上Phone屬性時都會被執行的OnPhoneChanging方法。使用該方法來驗證輸入,如果驗證成功,則從該方法中返回并且LINQ to SQL會認定該值是有效的,否則就會在該驗證方法中產生一個異常——防止發生賦值操作。
自定義實體對象驗證支持
屬性級別的驗證對于驗證數據模型類上獨立的屬性是十分有效的。但有時卻需要同時驗證一個對象上的多個屬性。考慮這樣一個場景,同時設置Order對象上的OrderDate和RequiredDate屬性:
以上的代碼從單純的SQL構架方面來說是合法的——即使規定交貨日期是訂單下達日期的前一天是毫無意義的。好消息是現在在Beta2(.NET Framework 3.5)中LINQ to SQL可以十分簡單地添加自定義實體級別的驗證規則來防止類似的錯誤發生。可以為Order實體類添加一個局部類,并實現OnValidate()局部方法,該方法會在實體的值將要記錄進數據庫的時候被調用。使用該驗證方法可以訪問和驗證所有的數據模型類屬性:
?
使用該驗證方法我們可以檢查實體類上的任何屬性值(即使對于它的管理對象只獲得只讀訪問),如果驗證的值不正確就可以產生一個異常。從OnValidate()方法中產生的任何異常都導致從數據庫更新操作中退出,并且回滾該操作所在事務中的所以更改。
自定義實體插入/更新/刪除方法驗證
在實際應用中,有時我們會需要對于特定的插入,更新或刪除場景來添加驗證邏輯。在Beta2(.NET Framework 3.5)中LINQ to SQL可以通過添加局部類型來擴展DataContext類,然后實現相應的局部方法來為數據模型實體自定義插入,更新和刪除邏輯。當調用DataContext類上的SubmitChanges()方法時,這些方法會被自動調用。
使用這些方法添加適當的驗證邏輯后,如果驗證通過就會通知LINQ to SQL繼續進行數據庫更新操作(通過調用DataContext類中的“ExecuteDynamicXYZ”方法):
適當地添加以上方法后,對于數據對象的任何創建/更新/刪除操作都會自動調用這些方法。例如,考慮這樣一個場景,創建一個新的Order并關聯到一個已存在的Customer上:
?
當在上面的示例代碼中調用northwind.SubmitChanges()時,LINQ to SQL會確認是否需要插入一個新的Order對象,并自動調用InsertOrder局部方法。
高級:為事務察看實體變化
在實際應用中,有時不能單純地通過察看單獨的插入/更新/插入操作來添加驗證邏輯,而是應察看一個以事務發生的實體操作變化列表。從.NET Framework 3.5 Beta2開始,我們可以通過調用公共的DataContext.GetChangeSet()方法來訪問這個變化列表。該方法會返回一個暴露每個已作出的添加,修改和移除操作的ChangeSet對象。
還有一種可供選擇的方式是編寫DataContext的子類并覆寫SubmitChanges()方法。然后就可以為更新操作檢索ChangeSet,并執行任何自定義的數據驗證:
使用樂觀并發執行處理同時發生的變化
在多用戶數據庫系統中開發者需要考慮的事情之一,就是如何處理對于數據庫中數據同時發生的更新。例如,假設兩個用戶在同一應用程序中檢索同樣的Product對象,一個用戶更新RecorderLevel為0,而另一個更新為1。如果兩個用戶都要試圖保存Product的更新到數據庫,那么開發者就需要決定如何處理變化沖突。
一種方式是“讓后來的更新者獲勝”——這就意味者先來的用戶提交的值會在重大用戶沒有察覺的情況下丟失。這通常被認為是一種缺乏應用程序開發經驗的一種表現。
另一種而且是LINQ to SQL支持的方式是使用樂觀并發執行模型——如何數據庫中的原始值已經有其他更新操作事先要執行,LINQ to SQL會自動檢測發生地點。LINQ to SQL可以提供一個更改值的沖突列表給開發者,并且能夠調和分歧,或者是通過UI通知應用程序終端用戶來讓他們決定如何處理。
為插入/更新/刪除場景使用存儲過程或自定義SQL邏輯
對于數據庫開發者來說,好消息是LINQ to SQL提供了相當靈活的開發模型,可以讓開發者覆寫通過LINQ to SQL自動執行的動態SQL,并替代為調用自定義的插入,更新,刪除用的存儲過程。
一開始的時候,我們可以定義數據模型并使用LINQ to SQL自動處理插入,更新,刪除等邏輯。在稍后還可以自定義用于更新數據模型的存儲過程或SQL——不需要對使用數據模型的應用程序邏輯作出任何改變,也不需要對相應的數據驗證或業務規則邏輯作出任何改變。這就為應用程序的構建提供了大量的靈活性。
總結
除了一般的插入,更新,刪除操作,以及數據驗證外,通過這篇Post我們還應注意以下一些要點:
1.善于利用表之間的關系關聯進行數據更新
2.數據驗證和業務邏輯驗證的應用級別包括:構架級,實體級,屬性級,更新操作時驗證和以事務為單位的驗證
3.LINQ to SQL還可以有效地處理SQL注入攻擊
4.LINQ to SQL還可以自動處理事務
5.LINQ to SQL使用樂觀并發執行模型處理更新沖突
?
注:
??? 原文地址:http://www.cnblogs.com/xuhy-developer/articles/849281.html
總結
以上是生活随笔為你收集整理的转载:LINQ to SQL更新数据库操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FPA笔记六 计算EI/EO/EQ的功能
- 下一篇: SQL Server根据访问历史日志分析