ASP.NET 3.5核心編程學習筆記(23):Linq-to-SQL 資料的更新、事務、預存程序、函數

來源:互聯網
上載者:User
  一旦實體物件被載入到記憶體中,插入新訂單的工作就非常簡單,無非是建立Order類的執行個體並將其添加到客戶對象的Orders集合中。Linq-to-SQL會跟蹤資料內容中的更改,並在調用資料內容對象的SubmitChanges時將那些更改傳回資料庫。下例顯示了一個更改資料的過程:

string id = "ALFKI";
Customer c = dataContext.Customers.SingleOrDefault(c => c.CustomerID == id);
if(c != null)
{
//修改資料
c.Address = "123 Flowers Streat);
//提交更改到資料庫中
dataContext.SubmitChanges();
}

對象的添加與刪除

  資料內容對象會自動跟蹤添加到內容相關的對象,並跟蹤已被更新、刪除或添加的對象。調用SubmitChanges方法會指示資料內容類,針對底層的資料庫,將暫止的變更轉化為更新語句。

  添加新記錄樣本:

Customer customer = new Customer();
customer.CustomerID = "KOEN2";
customer.CompanyName = "...";
...
dataContext.Customers.InsertOnSubmit(customer);
dataContext.SubmitChanges();

  刪除樣本:

Customer koen2 = dataContext.Customers.SingleOrDefault(c => c.CustomerID == "KOEN2");
if(koen2 != null)
{
dataContext.Customers.DeleteOnSubmit(koen2);
dataContext.SubmitChanges();
}

  在成功執行SubmitChanges後,已刪除對象在資料內容中會被標記為Deleted,而不會將其從內部緩衝中實際刪除。

跨表更新

  Linq-to-SQL使我們能夠在資料內容中對錶間關係進行建模,也支援跨表更新。我們要做的只是從相應的Table對象中將對象移除,其餘的工作由SubmitChanges完成。

//建立客戶
Customer mands = new Customer();
//mands的屬性賦值
...
dataContext.Customers.InsertOnSubmit(mands);

//添加訂單
Order order = new Order();
//為order的屬性賦值
...
//將訂單添加到mands的Orders屬性中
mands.Orders.Add(order);

//提交更改到資料庫中
dataContext.SubmitChanges();

  刪除上例中添加的客戶與訂單:

//取出客戶的訂單
var orders = from o in dataContext.Orders
where o.CustomerID == "MANDS"
select o;

//刪除訂單
foreach(var o in orders)
dataContext.Orders.DeleteOnSubmit(o);

//取出客戶對象
Customer mands = dataContext.Customers.SingleOrDefault(c => c.CustomerID == "MANDS");
if(mands != null)
{
//刪除客戶並提交更改到資料庫中
dataContext.Customers.DeleteOnSubmit(mands);
dataContext.SubmitChanges();
}

  注意,我們應該首先刪除客戶訂單,然後再刪除該客戶。如果先刪除客戶,因為客戶表與訂單表存在表間約束,將引發異常。

開放式並發

  以上例為例,我們在刪除訂單時如果使用SQL Profile工具跟蹤SQL實際執行的語句,可發現它執行的是如下的語句:

Delete From dbo.Customers
Where CustomerID = 'MANDS'
and CompanyName = 'Managed Design'
and ContactName = 'Dino'
and ContactTitle is NULL
and Address = 'Via dei Tigli'
and City = 'Milan'
and Region is NULL
and PostalCode is NULL
and Country = 'Italy'
and Phone is NULL
and Fax is NULL

  這種技術稱為“開放式並發”,它要求在更新和刪除記錄前,檢測是否有其他事務對該記錄做了修改。“保守式並發”在更新或刪除時,為避免衝突,會對記錄加鎖。預設情況下,Linq-to-SQL使用的是開放式並發。

  我們可以將一個參數傳給SubmitChanges,指示它忽略衝突異常並繼續執行:

dataContext.SubmitChanges(ConflictMode.ContinueOnConflict);

  預設值為ConflictMode.FailOnFirstConflict。如果選擇繼續更新,如何獲知哪些命令失敗呢?

  為此,我們可以遍曆資料內容的ChangeConflicts集合:

try
{
dataContext.SubmitChanges(ConflictMode.ContinueOnConflict);
}
catch(ChangeConflictException e)
{
foreach(ObjectChangeConflict occ in dataContext.ChangeConflicts)
{}
}

  ObjectChangeConflict類中定義的屬性使我們能瞭解到底發生了什麼,在哪張表上發生的,以及涉及了哪個實體物件。

更新操作的自訂

  為刪除某個客戶的所有訂單,如果不使用LINQ,我們可能會這樣做:

Delete From orders Where customerid = 'MANDS'

  Linq-to-SQL提供了一種方法,可以更改實體物件更新操作的實現。由於Linq-to-SQL構建於部分類別之上,我們只要添加一個分部方法就可以了。

  下面是Customer實體的資料內容類,可以通過分部方法擴充列表:

partial void InsertCustomer(Customer instance);
partial void UpdateCustomer(Customer instance);partial void DeleteCustomer(Customer instance);

  這類方法的形式為InsertXxx、UpdateXxx、DeleteXxx,其中Xxx代表資料內容中實體的名稱。這樣,在刪除客戶記錄時,我們可以這樣做:

partial void DeleteCustomer(Customer instance)
{
this.ExecuteCommand("Delete From customers Where customerid={0}", instance.CustomerID);
}

  使用此擴充方法後,在刪除客戶記錄時自動刪除相關訂單。

  我們還可以用更新操作的自訂特性,用預存程序代替T-SQL命令來執行資料庫操作。

使用事務

  通過SubmitChanges提交的所有更新都會在一個事務中進行。調用該方法後,Linq-to-SQL會驗證當前調用是否處於其他事務的作用範圍,確保使用者發起的事務沒有顯式地綁定到資料內容。如果沒有現有事務,Linq-to-SQL會啟動一個本地事務,並使用該事務執行所有T-SQL命令。當所有命令都執行完畢後,Linq-to-SQL會提交該事務。

  我們可以在自己的代碼中使用TranscationScope對象封裝由SubmitChanges方法引發的任何資料庫操作。如,通過外部的TranscationScope對象,我們可以將其他的非資料庫資源引入到事務中,可以向MSMQ發送訊息,也可以是更新檔案系統。若SubmitChanges檢測到自身處於某個現有事務的範圍內,它不僅會避免新事務的建立,而且還會避免串連的關閉。

  我們還可自行發起一個事務,將多個SubmitChanges的命令與該事務關聯。為此,我們可使用資料內容對象的Transaction屬性。提交或復原完全取決於開發人員。如果事務的連接字串與資料內容所使用的不匹配,則會有異常拋出。

使用預存程序

  我們可以在分部方法中使用ExecuteCommand方法執行預存程序。樣本:

partial void DeleteCustomer(Customer instance)
{
this.ExecuteCommand("exec delete_customer {0}", instance.CustomerID);
}

  此外,我們可以在VS2008的O/R設計器將預存程序添加到資料內容中,就可將預存程序當成資料內容的方法來調用。

  假設我們已將名為CustOrderHist的預存程序添加到資料內容中,調用方法如下:

var orders = dataContext.CustOrderHist(customerID);

  我們可使用var關鍵字對結果類型進行推斷。若預存程序返回多個值或不同類型的值,資料內容中該預存程序的封裝器會返回IMultipleResults類型,在這種情況下,我們可使用GetResult<T>來訪問給定的結果。其中T用於指定特定結果的類型。

使用使用者定義的函數

  與預存程序類似,使用者在資料庫中的自訂函數也可附加到資料內容中,並在頁面中以方法的形式調用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.