WCF RIA Service是一種簡化RIA資料庫存取的解決方案,基本上它以Entity Framework、WCF為基礎,透過服務元件、IDE精靈、程式碼自動產生器,讓Silverlight開發人員花最少的力氣搞定資料庫的查詢新增修改刪除工作。

(想多了解一點的人可以參考MSDN Library和Silverlight網站的錄影教學,另外,LOLOTA也有一篇簡單扼要的介紹文。)

今天第一次嘗試將WCF RIA Service應用在小型專案上,一度射門中柱彈出,所幸稍後頭鎚補進。

我寫的RIA Service是用來讓Silverlight查詢Oracle資料庫,EF部分利用devart提供的Devart Entity Model(說實在話,我還是偏好較輕巧的LINQ to ORACLE,過去也發過好人卡給EF。但EF畢竟是微軟力捧的掌上明珠,比起來LINQ to SQL只是灰姑娘,RIA Service只支援EF也算印證了這點),其餘部分倒如教學文件一樣簡單順利,Visual Studio 2010 IDE做掉了大部分的苦工,三兩下程式就寫好了。

正當我感覺自已即將跟灰姑娘她姐共享榮華富貴,自此過著幸福快樂日子時,RIA Service菜鳥王子忽然被一盆涼水潑醒。

當Silverlight端透過Proxy Class,向Domain Service Class查詢資料表內容時,出現以下錯誤:

An unhandled exception ('Unhandled Error in Silverlight Application
Code: 4004   
Category: ManagedRuntimeError      
Message: System.ServiceModel.DomainServices.Client.DomainOperationException: Load operation failed for query 'GetEntities'. The remote server returned an error: NotFound. ---> System.ServiceModel.CommunicationException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound. ---> System.Net.WebException: The remote server returned an error: NotFound.
   at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
   at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4(Object sendState)
   at System.Net.Browser.AsyncHelper.<>c__DisplayClass2.<BeginOnUI>b__0(Object sendState)
   --- End of inner exception stack trace ---
   at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
   at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.CompleteGetResponse(IAsyncResult result)
   --- End of inner exception stack trace ---
   at System.ServiceModel.DomainServices.Client.WebDomainClient`1.EndQueryCore(IAsyncResult asyncResult)
   at System.ServiceModel.DomainServices.Client.DomainClient.EndQuery(IAsyncResult asyncResult)
   at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.ServiceModel.DomainServices.Client.OperationBase.Complete(Exception error)
   at System.ServiceModel.DomainServices.Client.LoadOperation.Complete(Exception error)
   at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult asyncResult)
   at System.ServiceModel.DomainServices.Client.DomainContext.<>c__DisplayClass1b.<Load>b__17(Object )    
') occurred in iexplore.exe [8472].

NotFound? 網頁查不到?? 爬了文,發現原來NotFound只是"存取WCF時發生一般性錯誤"的一級模糊訊息,此時得使用Fiddler等網路封包監看工具才能找出問題根源。

使用HttpWatch Pro查看,菜鳥王子對RIA Service又多了一點了解。原來Silverlight會透過/ClientBin/DomainClassName.svc/binary/GetEntities的URL呼叫Domain Service Class,而我所得到的NotFound錯誤應是Response完全沒有傳回任何內容所致。

做了Line-By-Line Debug,確定Domain Service Class裡的GetEntities()有正確完成查詢並取得ORACLE資料,顯然問題是出在傳回前端時,但由於WCF的部分被Domain Service Hosting所掌控,無從Debug,只好透過調整程式碼觀察結果變化。做了一些測試,加上噗友補充,發現程式的問題出在傳回資料量太大,超出WCF限制。Domain Service Class自動建立的GetEntities程式碼預設會傳回整個資料表,當不是用AdventureWorks範例資料庫而是實務資料時,傳回資料量就可能大到突破WCF RIA Service的基底限制。

只是很不幸地,WCF只是無聲無息地自盡,沒提供任何線索,才讓我迷途這麼久。但藉著這個案例,我多學會一些WCF偵錯上的小技巧,留待下回分解。


Comments

# by programlin

這問題目前RIA Service Toolkit已有機制處理了 參考 http://www.dotblogs.com.tw/programlin/archive/2010/11/11/19361.aspx

Post a comment