使用LINQ和ADO.NET創(chuàng)建Silverlight程序
原創(chuàng)【51CTO.com獨(dú)家特稿】在Silverlight中可以創(chuàng)建行業(yè)和其它以數(shù)據(jù)為中心的應(yīng)用系統(tǒng),但在Silverlight中處理數(shù)據(jù)不是一件容易的事情,由于Silverlight包括許多處理數(shù)據(jù)和支持Web Service及XML的工具,但這些工具僅代表跨過(guò)防火墻進(jìn)行數(shù)據(jù)訪問(wèn)的最基礎(chǔ)的部分。
常見(jiàn)的數(shù)據(jù)訪問(wèn)策略是使用Web Service和客戶端LINQ共同實(shí)現(xiàn)的,如果你正在修改現(xiàn)有Web Service端點(diǎn)強(qiáng)化你的Silverlight應(yīng)用程序,那么我推薦你使用這個(gè)方法。但如果你在使用Silverlight創(chuàng)建一個(gè)新的Web Service,就沒(méi)有必要這么做了。
對(duì)一個(gè)典型的Web Service層而言,你在服務(wù)器上實(shí)現(xiàn)一個(gè)傳統(tǒng)的數(shù)據(jù)訪問(wèn)策略(自定義業(yè)務(wù)對(duì)象、LINQ to SQL、實(shí)體框架、Nhibernate等)通過(guò)Web Service暴露數(shù)據(jù)對(duì)象,Web Service僅僅是數(shù)據(jù)訪問(wèn)策略下面的網(wǎng)關(guān)。
但為了開(kāi)啟完整的數(shù)據(jù)連通性,你必須要映射四個(gè)數(shù)據(jù)操作(創(chuàng)建、讀取、更新和刪除)到Web Service方法,下面是一個(gè)簡(jiǎn)單的支持Product類的service contract,注意我在本文中使用的都是C#。
例1 Product Web Service的Service Contract
[ServiceContract] public interface ICustomerService { [OperationContract] List |
創(chuàng)建一套服務(wù)來(lái)處理應(yīng)用程序完整的數(shù)據(jù)模型可能是相當(dāng)費(fèi)時(shí)的,正如這個(gè)例子中顯示的,特殊特性的操作可能導(dǎo)致Web Service非常臃腫,換句話說(shuō),Web Service將有新的要求和操作要增加,甚至包括不屬于核心業(yè)務(wù)域的操作。
在例1中你看到GetAllProductsWithCategories操作默認(rèn)用于檢索Product和分類。即使添加排序、過(guò)濾和分頁(yè)機(jī)制到這個(gè)簡(jiǎn)單的例子你也不要感到驚訝,如果有一個(gè)簡(jiǎn)單的方法支持?jǐn)?shù)據(jù)操作(如查詢、排序、過(guò)濾等)不用每次都手動(dòng)構(gòu)建這些機(jī)制那將是非常吸引人的,ADO.NET Data Service就正是為此而生的。
ADO.NET Data Service
ADO.NET Data Service的目標(biāo)是為數(shù)據(jù)模型提供Web訪問(wèn)端點(diǎn),這些端點(diǎn)提供了數(shù)據(jù)排序、過(guò)濾、調(diào)整和分頁(yè)功能,因此開(kāi)發(fā)人員就不需要在自己去編寫(xiě)這部分代碼了,實(shí)際上,每個(gè)端點(diǎn)都是LINQ查詢的起點(diǎn),就從這個(gè)端點(diǎn)上你就可以查詢你想要查找的數(shù)據(jù)。
但不要認(rèn)為ADO.NET Data Service是另一個(gè)數(shù)據(jù)訪問(wèn)策略,實(shí)際上,ADO.NET Data Service不執(zhí)行任何直接的數(shù)據(jù)訪問(wèn)操作,它位于數(shù)據(jù)訪問(wèn)的上層,圖1顯示了ADO.NET Data Service和它在一個(gè)應(yīng)用程序架構(gòu)中的位置。
圖 1 ADO.NET Data Service層
由于ADO.NET Data Service依賴于數(shù)據(jù)訪問(wèn)程序完成真實(shí)的數(shù)據(jù)訪問(wèn)工作,你必須指定這個(gè)方法該如何做,在ADO.NET Data Service中,每個(gè)服務(wù)(Service)必須回到開(kāi)啟LINQ的提供程序的后面,實(shí)際上,每個(gè)端點(diǎn)就是一個(gè)Iqueryable端點(diǎn),因此ADO.NET Data Service支持任何支持Iqueryable的對(duì)象。
創(chuàng)建服務(wù)(Service)
當(dāng)你將ADO.NET Data Service添加到你的項(xiàng)目中時(shí),會(huì)創(chuàng)建一個(gè)新的.svc文件,代表一個(gè)服務(wù)的類,和Web Service不同,你不需要自己親自實(shí)現(xiàn)服務(wù)的操作,但要允許DataService類處理這些工作,為了運(yùn)行這些服務(wù),有兩個(gè)小任務(wù)必須執(zhí)行。首先,DataService類需要一個(gè)類型參數(shù)叫做上下文對(duì)象,它是將數(shù)據(jù)作為服務(wù)暴露的類,當(dāng)你的服務(wù)從關(guān)系數(shù)據(jù)庫(kù)暴露數(shù)據(jù)時(shí),這個(gè)類是從實(shí)體框架(EntityFramework)的ObjectContext或LINQ to SQL的DataContext衍生而來(lái)的。
//使用我的NorthwindEntities上下文對(duì)象(context object)作為服務(wù)(Service)的數(shù)據(jù)源
public class Products : DataService
上下文對(duì)象沒(méi)有基數(shù)類要求,實(shí)際上,你可以創(chuàng)建你自己的上下文對(duì)象,只要它的屬性實(shí)現(xiàn)了Iqueryable接口,ADO.NET Data Service將會(huì)以端點(diǎn)形式暴露這些屬性:
public class StateContext { StateList _states = new StateList(); public IQueryable |
InitializeService調(diào)用中,你可以使用IdataServiceConfiguration對(duì)象指定什么類型的許可允許進(jìn)入服務(wù),ADO.NET Data Service使用名詞和動(dòng)詞具體指定許可,如例2所示:
例2 設(shè)置訪問(wèn)規(guī)則
//這個(gè)方法只被調(diào)用一次初始化服務(wù)端策略 public static void InitializeService(IDataServiceConfiguration config) { //只允許我們讀取和更新Products實(shí)體,不允許刪除和創(chuàng)建 config.SetEntitySetAccessRule("Products", EntitySetRights.AllRead | EntitySetRights.WriteUpdate); //只允許讀取Category和Suppliers實(shí)體 config.SetEntitySetAccessRule("Categories", EntitySetRights.AllRead); config.SetEntitySetAccessRule("Suppliers", EntitySetRights.AllRead); } |
完成這個(gè)之后,你可以直接瀏覽服務(wù)了,它將會(huì)顯示每個(gè)端點(diǎn)的原子反饋信息,為了調(diào)試ADO.NET Data Service,我建議你禁用Internet Explorer的RSS 反饋視圖,或使用另一個(gè)瀏覽器查看服務(wù)的XML格式。
#p#
查詢和更新數(shù)據(jù)
ADO.NET Data Service將服務(wù)作為具有代表性的狀態(tài)轉(zhuǎn)換器(Representational State Transfer (REST))暴露,它是一個(gè)基礎(chǔ)服務(wù),不是基于SOAP的服務(wù),這意味著要替換掉SOAP封包,服務(wù)響應(yīng)的有效負(fù)載只包括數(shù)據(jù),不包括原數(shù)據(jù)(metadata),所有請(qǐng)求都使用HTTP動(dòng)詞(GET,PUT,POST等)和請(qǐng)求URI描述,假定你有一個(gè)如圖2所示的模型描述Products,Categories和Suppliers,ADO.NET Data Service服務(wù)將會(huì)產(chǎn)生三個(gè)端點(diǎn),每個(gè)實(shí)體集一個(gè),URI為了確定一個(gè)模型中的實(shí)體集,只需要使用服務(wù)的地址和端點(diǎn)的名字就可以了:http://localhost/{服務(wù)名}/{端點(diǎn)名}或http://localhost/Product.svc/Products。
圖 2 數(shù)據(jù)模型示例
URI語(yǔ)法支持許多不同的特性,包括檢索特殊的實(shí)體,對(duì)結(jié)果進(jìn)行排序、過(guò)濾、分頁(yè)和調(diào)整。
ADO.NET Data Service使用這些URI風(fēng)格的查詢將數(shù)據(jù)返回給服務(wù)的用戶,目前支持兩個(gè)序列化格式(將來(lái)的版本很可能會(huì)進(jìn)行擴(kuò)展):JavaScript對(duì)象標(biāo)記(JavaScript Object Notation即JSON)和基于原子的XML(Atom-based XML)。JSON對(duì)于客戶端Web代碼非常有吸引力,而Atom是基于XML的格式,因此需要借助XML解析器。
ADO.NET Data Service在查詢中使用標(biāo)準(zhǔn)的HTTP訪問(wèn)頭來(lái)確定向客戶端返回什么格式,如果你從客戶端(如一個(gè)瀏覽器)發(fā)出一個(gè)請(qǐng)求可以破壞XML,如果你不通過(guò)Accept頭指定一個(gè)優(yōu)先選用的格式,默認(rèn)將使用Atom作為返回的格式。
查詢數(shù)據(jù)只是解決方案的一部分,我們的最終目標(biāo)是同時(shí)支持查詢和更新,為了支持這些要求,ADO.NET Data Service映射了四個(gè)最基本的數(shù)據(jù)訪問(wèn)操作到基本的HTTP動(dòng)詞(如表1所示):
數(shù)據(jù)訪問(wèn)動(dòng)詞 | HTTP動(dòng)詞 |
Create | POST |
Read | GET |
Update | PUT |
Delete | DELETE |
表 1 數(shù)據(jù)訪問(wèn)動(dòng)詞 vs HTTP動(dòng)詞
通過(guò)使用這些動(dòng)詞,ADO.NET Data Service讓服務(wù)的用戶可以利用所有的數(shù)據(jù)操作類型,而不用為不同類型創(chuàng)建專門(mén)的端點(diǎn)。使用ADO.NET Data Service更新數(shù)據(jù)的唯一要求是在數(shù)據(jù)訪問(wèn)技術(shù)下支持Iupdatable接口,這個(gè)接口定義了如何從ADO.NET Data Service更新和傳播到數(shù)據(jù)源。
Silverlight 2.0客戶端庫(kù)
如果你使用ADO.NET Data Service通過(guò)URI語(yǔ)法和操作XML來(lái)進(jìn)行查詢和更新數(shù)據(jù),你可能會(huì)得到你想要的許多功能,但你仍然要自行構(gòu)建一些管道,ADO.NET Data Service客戶端庫(kù)的引入就是要解決這個(gè)問(wèn)題,這個(gè)庫(kù)允許你直接在Silverlight程序中進(jìn)行LINQ查詢,由客戶端庫(kù)將LINQ查詢翻譯成HTTP查詢或更新請(qǐng)求。
首先,你需要生成一些代碼,這些代碼讀取ADO.NET Data Service服務(wù)的元數(shù)據(jù),并為服務(wù)的實(shí)體生成數(shù)據(jù)類。
為了生成這些代碼,你需要在你的項(xiàng)目(Project)中添加Service Reference,你可以在項(xiàng)目資源管理器(Project Explorer)中Silverlight項(xiàng)目上點(diǎn)擊右鍵,然后選擇‘添加服務(wù)引用(即Add Service Reference)’,在彈出的對(duì)話框中點(diǎn)擊‘查找(Discover)’按鈕,顯示你項(xiàng)目中的服務(wù)(包括ADO.NET Data Service),選擇ADO.NET Data Service端點(diǎn),點(diǎn)擊確定按鈕。這樣會(huì)創(chuàng)建一個(gè)新的文件,包含了每個(gè)端點(diǎn)對(duì)應(yīng)的data contract類和一個(gè)DataServiceContext衍生類,DataServiceContext類用作服務(wù)接入點(diǎn)(暴露可查詢的服務(wù)端點(diǎn)),這樣會(huì)在你的Silverlight項(xiàng)目中包含這些類,并在System.Data.Services.Client.dll(Silverlight 2 SDK的一部分)中添加一個(gè)引用。Silverlight客戶端代碼和其它使用.NET的代碼基于LINQ的查詢非常相似,下面是示例代碼:
// 創(chuàng)建服務(wù)類指定ADO.NET Data Service的位置 NorthwindEntities ctx = new NorthwindEntities(new Uri("Products.svc", UriKind.Relative)); //創(chuàng)建LINQ查詢 var qry = from p in ctx.Products orderby p.ProductName select p; |
當(dāng)你執(zhí)行這個(gè)查詢時(shí),它會(huì)直接向目標(biāo)數(shù)據(jù)發(fā)送一個(gè)Web請(qǐng)求,但這里的Silverlight代碼和標(biāo)準(zhǔn)的LINQ查詢不同,在Silverlight中不允許同步Web請(qǐng)求,因此,如果要執(zhí)行異步,你首先需要將查詢轉(zhuǎn)換成DataServiceQuery
// 創(chuàng)建一個(gè)DataServiceQuery |
當(dāng)這些查詢執(zhí)行完后,無(wú)論操作是否成功,在AsyncCallback中指定的方法都會(huì)執(zhí)行,通常你會(huì)在AsyncCallback中包含原始查詢,因此可以在callback方法中檢索它,你也可以將其保存為類的一部分,正如你在例3中看到的:
例3 將結(jié)果添加到集合中
void OnLoadComplete(IAsyncResult result) { //為查詢獲取一個(gè)引用 DataServiceQueryproductQuery = (DataServiceQuery )result.AsyncState; try { //獲得結(jié)果并將其添加到集合中 List products = productQuery.EndExecute(result).ToList(); } catch (Exception ex) { if (HtmlPage.IsEnabled) { HtmlPage.Window.Alert("Failed to retrieve data: " + ex.ToString()); } } }
如果你以前還沒(méi)有處理過(guò)LINQ,理解這些模型可能就非常困難,在寫(xiě)本文的時(shí)候,除了在異步包中執(zhí)行LINQ(如ThreadPool和BackgroundWorker)外,還沒(méi)有關(guān)于異步LINQ很好的模型,Silverlight需要所有的請(qǐng)求都是異步的,因此在使用ADO.NET Data Service客戶端庫(kù)時(shí)需要使用這個(gè)模型。
載入相關(guān)實(shí)體
ADO.NET Data Service也允許你選擇如何載入相關(guān)的實(shí)體,在前面的例子中,我是從服務(wù)器中載入Products(產(chǎn)品)的,每個(gè)產(chǎn)品與供應(yīng)商都有一個(gè)關(guān)系。使用前面的LINQ查詢,我們只檢索了產(chǎn)品,如果我還想顯示供應(yīng)商和分類信息,我們可以按需載入相關(guān)信息,也可以在原始查詢中明確地從服務(wù)器去檢索,這兩種技術(shù)各有各的優(yōu)勢(shì),但如果你清楚地知道需要顯示哪些信息,明確地載入可能更有效,如果你只想為一些實(shí)體載入數(shù)據(jù),使用按需檢索可能會(huì)更好。
默認(rèn)情況下,如果你沒(méi)有明確地載入屬性,關(guān)系屬性(如產(chǎn)品供應(yīng)商)就是空的,為便于按需載入,DataServiceContext類有一個(gè)BeginLoadProperty方法(遵循相同的異步模式)可以指定源實(shí)體,屬性名和callback。
|
調(diào)用EndLoadProperty后,屬性和相關(guān)的實(shí)體就被正確地載入,在許多情況下,你可能想在原始查詢中明確地載入它們,因?yàn)槿绱?,LINQ提供者支持Expand擴(kuò)展方法,這個(gè)方法允許你指定屬性的名稱路徑便于查詢執(zhí)行時(shí)載入它們,Expand方法在LINQ查詢的from子句中使用,它告訴提供者視圖載入這些相關(guān)實(shí)體,例如,如果你使用Expand方法改變了Category 和 Supplier原始查詢,在原始查詢執(zhí)行期間,我們的對(duì)象將會(huì)載入這些相關(guān)實(shí)體:
|
如果你使用ADO.NET Data Service讀取數(shù)據(jù),知道如何創(chuàng)建一個(gè)查詢,運(yùn)行它,載入你想要的相關(guān)實(shí)體。如果你需要真實(shí)地修改數(shù)據(jù),只需要將你的新數(shù)據(jù)綁定到你的Silverlight控制器即可。
#p#
變化管理
ADO.NET Data Service客戶端庫(kù)不支持對(duì)象的自動(dòng)變更監(jiān)視,這意味著當(dāng)對(duì)象,集合和關(guān)系發(fā)生變化時(shí),需要開(kāi)發(fā)人員告訴DataServiceContext這些變化,通知DataServiceContext對(duì)象的API相當(dāng)簡(jiǎn)單,如例4所示:
例4 DataServiceContext變更API
方法 | 描述 |
AddObject | 添加一個(gè)新創(chuàng)建的對(duì)象 |
UpdateObject | 標(biāo)記一個(gè)已經(jīng)變化的對(duì)象 |
DeleteObject | 標(biāo)記一個(gè)刪除的對(duì)象 |
AddLink | 在兩個(gè)對(duì)象之間添加一個(gè)鏈接 |
UpdateLink | 更新兩個(gè)對(duì)象之間的鏈接 |
DeleteLink | 刪除兩個(gè)對(duì)象之間的鏈接 |
這意味著你要監(jiān)視對(duì)象的變化,并在你自己的代碼中通知DataServiceContext對(duì)象,表面上看起來(lái)這樣讓人很失望,因?yàn)闆](méi)有實(shí)現(xiàn)自動(dòng)化的變化管理,但這樣可以讓庫(kù)變得更有效也更mini。
你可能會(huì)對(duì)如何監(jiān)視對(duì)象的變化感到奇怪,答案就是生成的代碼中,在每個(gè)生成的data contract類中,當(dāng)類中的數(shù)據(jù)變化時(shí)partial方法被調(diào)用,如果這些方法從來(lái)沒(méi)有使用過(guò),它們本身不會(huì)造成任何資源消耗,你可以在任何支持變化通知的data contracts上使用partial方法機(jī)制,只需要在partial方法中調(diào)用DataServiceContract即可,不用連接DataServiceContract整個(gè)類。
幸運(yùn)的是,Silverlight已經(jīng)有一個(gè)接口支持變化通知了(INotifyPropertyChange),通過(guò)這個(gè)接口可以在你的實(shí)現(xiàn)中將任何變化通知給感興趣的人,例如你可以在你的data contract類(在我們的例子中是Product類)中調(diào)用InotifyPropertyChange定義一個(gè)事件,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)可以激活它,下面就是具體的示例:
public partial class Product : INotifyPropertyChanged |
這樣當(dāng)任何屬性發(fā)生變化時(shí)都可以觸發(fā)一個(gè)事件,你可以通過(guò)partial方法決定什么時(shí)候觸發(fā)這個(gè)事件,例如,當(dāng)ProductName發(fā)生變化時(shí)要通知預(yù)定人,只需要調(diào)用OnProductNameChanged方法,然后觸發(fā)PropertyChanged事件,傳遞ProductName通知變化的屬性給事件預(yù)定人,下面是代碼:
|
通過(guò)在這些可寫(xiě)的屬性上調(diào)用這些partial方法,監(jiān)視你對(duì)象的變化就很簡(jiǎn)單了,當(dāng)對(duì)象發(fā)生變化時(shí),你可以注冊(cè)PropertyChanged事件然后通知DataServiceContext對(duì)象:
|
最后你可以調(diào)用product_PropertyChanged方法通知DataServiceContext對(duì)象:
void product_PropertyChanged(object sender, PropertyChangedEventArgs e) |
同樣,在創(chuàng)建對(duì)象或刪除對(duì)象時(shí)也需要通知DataServiceContext,如:
void addNewButton_Click(object sender, RoutedEventArgs e) { Product theProduct = new Product(); // ... TheContext.AddObject(theProduct); } void deleteButton_Click(object sender, RoutedEventArgs e) { Product theProduct = (Product)theList.SelectItem; TheContext.DeleteObject(theProduct); theCollection.Remove(theProduct); } |
在這些代碼中,你可以在你的Silverlight UI中修改這些對(duì)象,讓數(shù)據(jù)綁定和變化通知代碼確保讓DataServiceContext知道所有變化都會(huì)引發(fā)什么后果,但你如何對(duì)這些服務(wù)執(zhí)行真實(shí)的更新呢?
通過(guò)服務(wù)更新
現(xiàn)在你的DataServiceContext對(duì)象已經(jīng)知道數(shù)據(jù)的變化,但還需要一個(gè)方法通知給服務(wù)器,為了解決這個(gè)問(wèn)題,DataServiceContext類提供了一個(gè)BeginSaveChanges方法,它和本文前面描述的查詢都使用了相同的異步方法,BeginSaveChanges方法將所有變化都吸收進(jìn)DataServiceContext,并將它們發(fā)送給服務(wù)器:
|
調(diào)用BeginSaveChanges時(shí),有一個(gè)標(biāo)志枚舉調(diào)用SaveChangesOptions,這個(gè)枚舉允許你指定兩個(gè)選項(xiàng):是否使用批處理,是否繼續(xù),即使某些變化保存失敗。通常,我建議使用批處理,實(shí)際上,在某些父/子關(guān)系類型上批處理是必須的,因?yàn)楦缸又g可能使用了引用完整性約束,這樣更新才能保證父子之間的一致性。
保存完畢時(shí),將會(huì)執(zhí)行callback,有兩個(gè)機(jī)制可以傳播錯(cuò)誤消息給你,首先,如果在執(zhí)行保存時(shí)出現(xiàn)了異常,當(dāng)你在調(diào)用EndSaveChanges時(shí),會(huì)拋出異常,因?yàn)槿绱?,你可能想要使用try/catch來(lái)捕獲災(zāi)難性的錯(cuò)誤;另外,EndSaveChanges返回的類型是一個(gè)DataServiceResponse對(duì)象,DataServiceResponse有一個(gè)HasErrors屬性,但在Silverlight 2 Beta 2版本庫(kù)中它還不夠安全:
void OnSaveAllComplete(IAsyncResult result) { bool succeeded = true; try { DataServiceResponse response = (DataServiceResponse)TheContext.EndSaveChanges(result); foreach (OperationResponse opResponse in response) { if (opResponse.HasErrors) { succeeded = false; } } } catch (Exception ex) { succeeded = false; } // Alert the User }
你可以重復(fù)使用OperationResponse對(duì)象來(lái)查看是否出現(xiàn)了錯(cuò)誤,DataServiceResponse是OperationResponse對(duì)象的一個(gè)集合,在以后的版本中,你應(yīng)該可以依賴于DataServiceResponse類自身的HasErrors屬性了。
服務(wù)調(diào)式
在調(diào)試服務(wù)時(shí),你要執(zhí)行三個(gè)重要的任務(wù):查看DataServiceContext對(duì)象中數(shù)據(jù)的狀態(tài),查看ADO.NET Data Services產(chǎn)生的請(qǐng)求,以及捕獲服務(wù)器錯(cuò)誤。
首先我們處理DataServiceContext對(duì)象中的實(shí)體狀態(tài),DataServiceContext類暴露了兩個(gè)有用的集合:Entities和Links,這些集合是只讀的,由DataServiceContext進(jìn)行跟蹤,在調(diào)式時(shí),不管你是將對(duì)象標(biāo)記為已變化還是未變化,在調(diào)試器中查看這些集合是非常有用的,可以幫助你確定跟蹤思路是不是正確的。
注意對(duì)你而言,查看你的Silverlight 2程序?qū)Ψ?wù)器的真實(shí)請(qǐng)求也是很重要的,最好的方法是使用網(wǎng)絡(luò)代理,我個(gè)人使用的是Fiddler2,如果你對(duì)Fiddler2不熟悉,也可以使用Web traffic之類的工具來(lái)捕獲數(shù)據(jù)包,查看真正發(fā)生了什么。
對(duì)于ADO.NET Data Service而言,你可能想查看你在線上傳來(lái)傳去的都是什么,即Silverlight程序發(fā)出的數(shù)據(jù)和接收到的數(shù)據(jù),可以去我的博客(http://wildermuth.com/2008/06/07/Debugging_ADO_NET_Data_Services_with_Fiddler)轉(zhuǎn)轉(zhuǎn)。
最后,.NET Framework 3.5 SP1不會(huì)將服務(wù)端錯(cuò)誤傳遞給客戶端了,實(shí)際上,服務(wù)器上的大部分錯(cuò)誤都是服務(wù)器吞下去的,調(diào)試服務(wù)端錯(cuò)誤的最好辦法是在調(diào)試菜單(Debug->Exceptions…)中使用Exception選項(xiàng),配置調(diào)試器停止一切.NET異常,如果你選擇了這個(gè)選項(xiàng),你可以通過(guò)服務(wù)看到拋出的異常。
我在本文的目標(biāo)是展示ADO.NET Data Service是如何在Silverlight 2和基于服務(wù)的模塊之間建立起連接的,現(xiàn)在你應(yīng)該已經(jīng)知道如何使用ADO.NET Data Service從服務(wù)器讀取數(shù)據(jù)和往服務(wù)器寫(xiě)數(shù)據(jù)了,再也不用自己動(dòng)手設(shè)計(jì)Web Service了,正如你所看到的,Silverlight、ADO.NET Data Service和LINQ三者的組合讓你可以創(chuàng)建強(qiáng)大的基于數(shù)據(jù)驅(qū)動(dòng)的Web應(yīng)用程序,具有Web 2.0技術(shù)的所有有點(diǎn)。
【編輯推薦】