日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

[WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)

發(fā)布時(shí)間:2023/11/27 生活经验 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

條件獲取(Conditional Update)可以避免相同數(shù)據(jù)的重復(fù)傳輸,進(jìn)而提高性能。條件更新(Conditional Update)用于解決資源并發(fā)操作問(wèn)題。如果我們預(yù)先獲取一個(gè)資源進(jìn)行修改或者刪除,條件更新檢驗(yàn)幫助我們確認(rèn)資源被獲取出來(lái)到針對(duì)它的修改/刪除操作被提交的這段時(shí)間內(nèi)是否被其他人改動(dòng)過(guò)。[源代碼從這里下載]

一、HTTP對(duì)條件更新的支持

HTTP為條件更新提供了相應(yīng)的報(bào)頭,我們按照分析條件獲取的方式來(lái)分析條件更新在HTTP請(qǐng)求/回復(fù)過(guò)程中的實(shí)現(xiàn)。客戶(hù)端第一次向服務(wù)端發(fā)起針對(duì)某個(gè)資源的請(qǐng)求,服務(wù)端除了將資源數(shù)據(jù)作為回復(fù)消息主體返回之外,會(huì)將與資源關(guān)聯(lián)并且能夠可以用于對(duì)其進(jìn)行對(duì)等性判斷的某個(gè)值作為回復(fù)的ETag報(bào)頭,這與條件獲取時(shí)一致的。

客戶(hù)端通過(guò)回復(fù)獲得請(qǐng)求的資源和ETag報(bào)頭值。對(duì)于資源修改操作,客戶(hù)端直接針對(duì)獲取的資源進(jìn)行相應(yīng)的修改,并將修改后的資源以HTTP請(qǐng)求的方式向服務(wù)端提交;對(duì)于資源刪除操作,則可以指定被刪除資源的唯一標(biāo)識(shí)直接向服務(wù)端發(fā)送刪除的請(qǐng)求。而之前獲取的ETag指將會(huì)作為請(qǐng)求消息的If-Match報(bào)頭。

服務(wù)端接收到資源修改/刪除請(qǐng)求后先獲取到現(xiàn)有的資源的ETag值,并將此值與請(qǐng)求消息的If-Match報(bào)頭值進(jìn)行比較。如果兩者不一致,則表明試圖被修改/刪除的資源已經(jīng)被修改了,在這種情況下會(huì)直接回復(fù)一個(gè)HTTP狀態(tài)為“412 (Precondition Failed)”的空消息。條件更新同時(shí)支持針對(duì)PUT、POST和DELETE這三種方法的HTTP請(qǐng)求。

二、WebOperationContext與條件更新

服務(wù)端進(jìn)行條件更新檢測(cè),以及客戶(hù)端對(duì)If-Match請(qǐng)求報(bào)頭的設(shè)置都可以通過(guò)當(dāng)前的WebOperationContext來(lái)完成。如下面的代碼片斷所示,表示入棧請(qǐng)求上下文的IncomingWebRequestContext類(lèi)型具有如下四個(gè)CheckConditionalUpdate方法重載用于進(jìn)行添加更新檢測(cè)。

   1: public class IncomingWebRequestContext
   2: {
   3:     //其他成員
   4:     public void CheckConditionalUpdate(Guid entityTag);
   5:     public void CheckConditionalUpdate(int entityTag);
   6:     public void CheckConditionalUpdate(long entityTag);
   7:     public void CheckConditionalUpdate(string entityTag);
   8: }

實(shí)現(xiàn)在CheckConditionalUpdate方法中的條件更新檢測(cè)具有這樣的邏輯:對(duì)于HTTP方法為PUT的請(qǐng)求,如果If-Match報(bào)頭值不為“*”,則直接拋出HTTP狀態(tài)為PreconditionFailed的WebFaultException異常;對(duì)于HTTP方法為POST和DELETE的請(qǐng)求來(lái)說(shuō),如果If-Match報(bào)頭值為“*”或者包含指定的entityTag則驗(yàn)證通過(guò),否則同樣則直接拋出HTTP狀態(tài)為PreconditionFailed的WebFaultException異常

表示出棧請(qǐng)求上下文的OutgoingWebRequestContext類(lèi)型具有如下一個(gè)IfMatch屬性,客戶(hù)端可以通過(guò)該屬性對(duì)請(qǐng)求消息的If-Match報(bào)頭進(jìn)行設(shè)置。

   1: public class OutgoingWebRequestContext
   2: {
   3:     //其他成員
   4:     public string IfMatch { get; set; }
   5: }

三、實(shí)例演示:通過(guò)條件更新解決對(duì)相同資源的并發(fā)修改

我們同樣通過(guò)對(duì)EmployeesService進(jìn)行相應(yīng)的改造來(lái)模擬如何通過(guò)添加更新實(shí)現(xiàn)對(duì)相同資源的并發(fā)操作問(wèn)題,這次我們修改的是用于獲取指定ID員工信息的Get操作和用于修改員工信息的Update操作。Get操作在返回與指定員工ID匹配的Employee對(duì)象之前我們將該對(duì)象的哈希碼作為了回復(fù)消息的ETag報(bào)頭(Employee類(lèi)型重寫(xiě)了GetHashCode方法)。

   1: public class EmployeesService : IEmployees
   2: {
   3:     //其他成員
   4:     public Employee Get(string id)
   5:     {
   6:         Employee employee = employees.FirstOrDefault(e => e.Id == id);
   7:         if (null == employee)
   8:         {
   9:             throw new WebFaultException(HttpStatusCode.NotFound);
  10:         }
  11:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
  12:         return employee;
  13:     }
  14:     public void Update(Employee employee)
  15:     {
  16:         var existing = employees.FirstOrDefault(e => e.Id == employee.Id);
  17:         if (null == existing)
  18:         {
  19:             throw new WebFaultException(HttpStatusCode.NotFound);
  20:         }
  21:         //模擬并發(fā)修改
  22:         existing.Name += Guid.NewGuid().ToString();
  23:? 
  24:         WebOperationContext.Current.IncomingRequest.CheckConditionalUpdate(existing.GetHashCode());
  25:         employees.Remove(existing);            
  26:         employees.Add(employee);
  27:         WebOperationContext.Current.OutgoingResponse.SetETag(employee.GetHashCode());
  28:? 
  29:     }
  30: }

Update方法中我們通過(guò)手工修改相應(yīng)員工的Name屬性的方式來(lái)模擬針對(duì)相同員工信息的并發(fā)修改。在真正實(shí)施修改之前調(diào)用當(dāng)前IncomingWebRequestContext的CheckConditionalUpdate方法進(jìn)行條件更新檢測(cè),而作為參數(shù)傳入的ETag值為代表目前員工的Employee對(duì)象的哈希碼。方法的最后我們對(duì)回復(fù)消息的ETag報(bào)頭作了更新。

我們通過(guò)手工創(chuàng)建HTTP請(qǐng)求的方式對(duì)上述的兩個(gè)服務(wù)操作進(jìn)行調(diào)用。如下面的代碼片斷所示,我們首先通過(guò)創(chuàng)建的HttpWebRequest對(duì)象調(diào)用Get操作獲得ID為001的員工信息并將其打印出來(lái)。然后創(chuàng)建調(diào)用Update操作的HttpWebRequest,并對(duì)HTTP方法(POST)和內(nèi)容類(lèi)型(application/xml)進(jìn)行了相應(yīng)的設(shè)置。我們之前針對(duì)員工獲取請(qǐng)求得到ETag報(bào)頭和員工數(shù)據(jù)作為本次請(qǐng)求的If-Match報(bào)頭和主體。如果調(diào)用GetResponse方法拋出WebException異常,并且其回復(fù)狀態(tài)為PreconditionFailed,則表明試圖修改的員工信息已被另一個(gè)用戶(hù)修改過(guò)了,所以我么打印“服務(wù)端數(shù)據(jù)已發(fā)生變化”字樣。

   1: Uri address = new Uri("http://127.0.0.1:3721/employees/001");
   2: var request = (HttpWebRequest)HttpWebRequest.Create(address);
   3: request.Method = "GET";
   4: var response = (HttpWebResponse)request.GetResponse();
   5: string employee;
   6: using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
   7: {
   8:     employee = reader.ReadToEnd();
   9:     Console.WriteLine("獲取員工信息:");
  10:     Console.WriteLine(employee + "\n");
  11: }
  12: try
  13: {
  14:     address = new Uri("http://127.0.0.1:3721/employees/");
  15:     request = (HttpWebRequest)HttpWebRequest.Create(address);
  16:     request.Method = "POST";
  17:     request.ContentType = "application/xml";
  18:     byte[] buffer = Encoding.UTF8.GetBytes(employee);
  19:     request.GetRequestStream().Write(Encoding.UTF8.GetBytes(employee), 0, buffer.Length);
  20:     request.Headers.Add(HttpRequestHeader.IfMatch, response.Headers[HttpResponseHeader.ETag]);
  21:     Console.WriteLine("修改員工信息:");
  22:     request.GetResponse();
  23: }
  24: catch (WebException ex)
  25: {
  26:     response = ex.Response as HttpWebResponse;
  27:     if (null == response)
  28:     {
  29:         throw;
  30:     }
  31:     if (response.StatusCode == HttpStatusCode.PreconditionFailed)
  32:     {
  33:         Console.WriteLine("服務(wù)端數(shù)據(jù)已發(fā)生變化");
  34:     }
  35:     else
  36:     {
  37:         throw;
  38:     }
  39: }

在服務(wù)成功寄宿的情況下調(diào)用這段程序會(huì)在控制臺(tái)上輸出如下的結(jié)果。由于并發(fā)錯(cuò)誤的發(fā)生,員工信息其實(shí)并沒(méi)有被真正修改。

   1: 獲取員工信息:
   2: <Employee xmlns="http://www.artech.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Department>開(kāi)發(fā)部</Department><Grade>G7</Grade><Id>001</Id><Name>張三</Name></Employee>
   3:? 
   4: 修改員工信息:
   5: 服務(wù)端數(shù)據(jù)已發(fā)生變化

轉(zhuǎn)載于:https://www.cnblogs.com/artech/archive/2012/02/14/wcf-rest-conditional-update.html

總結(jié)

以上是生活随笔為你收集整理的[WCF REST] 解决资源并发修改的一个有效的手段:条件更新(Conditional Update)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。