2010-08-19 44 views
5

新手,請耐心等待,因爲我昨天剛剛開始使用WCF。WCF與實體框架錯誤第二部分

我正在使用Northwind的數據,只將客戶,訂單,訂單詳細信息和產品添加到模型中,所以沒有什麼奇特。

當我啓動應用程序並調用Test並設置一個斷點時,產品的值就在那裏,並且完成時沒有錯誤。如果我然後嘗試調用GetMaxQuantityByOrderID(10248),我會在底部列出錯誤。爲什麼測試()工作和相同的方法WITHIN測試()不工作?我甚至添加了另一個(Test1(),與Test完全相同,除了它返回字符串:x.ProductName,它正確顯示Queso Cabrales)。似乎很奇怪的是,在另一個作品中被調用的方法,但直接調用它會導致異常。

我遇到的另一個問題是IEnumerable GetOrders()只在添加.ToList()時才起作用。沒有它(或with .AsEnumerable()),我得到一個錯誤(ObjectContext實例已經被處置,不能再用於需要連接的操作,),即使延遲加載設置爲False。這背後的邏輯是什麼?

IServiceTest.cs

using System.Collections.Generic; 
using System.ServiceModel; 

namespace WcfTestServiceLibrary 
{ 
    [ServiceContract] 
    public interface IServiceTest 
    { 

     [OperationContract] 
     IEnumerable<Orders> GetOrders(); 

     [OperationContract] 
     IEnumerable<Customers> GetCustomers(); 

     [OperationContract] 
     Customers GetCustomerByID(string customerID); 

     [OperationContract] 
     Orders GetOrderByID(int id); 

     [OperationContract] 
     IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id); 

     [OperationContract] 
     Order_Details GetMaxQuantityByOrderID(int id); 

     [OperationContract] 
     void Test(); 
    } 
} 

ServiceTest.cs

using System.Collections.Generic; 
using System.Linq; 

namespace WcfTestServiceLibrary 
{ 

    public class ServiceTest : IServiceTest 
    { 
     public IEnumerable<Orders> GetOrders() 
     { 
      using (var ctx = new NWEntities()) 
      { 
       return (from o in ctx.Orders.Include("Order_Details.Products").Include("Customers") 
         select o).ToList(); 
      } 
     } 

     public IEnumerable<Customers> GetCustomers() 
     { 
      using (var ctx = new NWEntities()) 
      { 
       return (from c in ctx.Customers 
         select c); 
      } 
     } 

     public Customers GetCustomerByID(string customerID) 
     { 
      return (from c in GetCustomers() 
        where c.CustomerID == customerID 
        select c).FirstOrDefault(); 
     } 

     public Orders GetOrderByID(int id) 
     { 
      IEnumerable<Orders> orders = GetOrders(); 
      return (from o in orders 
        where o.OrderID == id 
        select o).FirstOrDefault(); 
     } 

     public IEnumerable<Order_Details> GetOrderDetailsByOrderID(int id) 
     { 
      return GetOrderByID(id).Order_Details; 
     } 

     public Order_Details GetMaxQuantityByOrderID(int id) 
     { 
      Orders order = GetOrderByID(id); 
      return order == null ? null : order.Order_Details.OrderByDescending(x => x.Quantity).FirstOrDefault(); 

     } 

     public void Test() 
     { 
      const int orderID = 10248; 
      var oq = GetMaxQuantityByOrderID(orderID); 
      var x = oq.Products; 
     } 
    } 
} 

錯誤:

An error occurred while receiving the HTTP response to http://localhost:8732/Design_Time_Addresses/WcfTestServiceLibrary/Service1/. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down). See server logs for more details. 

Server stack trace: 
    at System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason) 
    at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) 
    at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) 
    at System.ServiceModel.Channels.ClientReliableChannelBinder`1.RequestClientReliableChannelBinder`1.OnRequest(TRequestChannel channel, Message message, TimeSpan timeout, MaskingMode maskingMode) 
    at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout, MaskingMode maskingMode) 
    at System.ServiceModel.Channels.ClientReliableChannelBinder`1.Request(Message message, TimeSpan timeout) 
    at System.ServiceModel.Security.SecuritySessionClientSettings`1.SecurityRequestSessionChannel.Request(Message message, TimeSpan timeout) 
    at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) 
    at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) 
    at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) 

Exception rethrown at [0]: 
    at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) 
    at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 
    at IServiceTest.GetMaxQuantityByOrderID(Int32 id) 
    at ServiceTestClient.GetMaxQuantityByOrderID(Int32 id) 

Inner Exception: 
The underlying connection was closed: An unexpected error occurred on a receive. 
    at System.Net.HttpWebRequest.GetResponse() 
    at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) 

Inner Exception: 
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. 
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) 
    at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) 
    at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead) 

Inner Exception: 
An existing connection was forcibly closed by the remote host 
    at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) 
    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) 

回答

1

對於第一個問題,嘗試打開WCF tracing您的服務。 IEnumerable的第二個問題是由於被執行的執行引起的。順便說一句。你瞭解IQueryable <T>和IEnumerable <T>之間的區別嗎?你知道你的GetOrders方法將所有訂單,相關客戶和產品加載到內存中嗎?即使您想選擇單個訂單,您仍然可以將所有這些訂單加載到服務中。

編輯:

WCF跟蹤將顯示您的服務或客戶端執行過程中發生了什麼 - 它跟蹤WCF內部,它是WCF開發必不可少的工具。 WCF跟蹤教程和trace viewer

IQueryable構建編譯到數據庫查詢中的表達式樹,因此您無法在上下文範圍外(上下文負責數據庫連接)執行該查詢(執行的執行)。你必須重寫你的方法。在你的情況下,每種方法都必須創建完整的查詢並在上下文範圍內執行該查詢。通過選擇單個記錄(如FirstOrDefault())或轉換爲列表來執行查詢。

+0

如果我更改爲IQueryable的,我得到了錯誤的ObjectContext的實例已設置,並且不能再被用於需要連接的操作。什麼是WCF服務的正確方法?我不明白什麼配置跟蹤將允許我做。正如我所說的,我剛剛在2天前開始使用WCF。 – 2010-08-19 13:03:41

+0

我添加了一些關於跟蹤和EF的信息。 – 2010-08-19 13:34:35

+0

該問題只出現在WCF測試客戶端中。如果我不使用客戶端並使用asp.net頁面來獲取結果,它就會起作用。 – 2010-08-24 02:35:37

8

我遇到了一個非常類似的問題。我發現包裝POCO類的實體框架代理默認由WCF序列化程序序列化,因爲客戶端不知道EF代理包裝程序,所以WCF序列化程序無法在客戶端反序列化。我找到了兩個解決方案。首先是將ContextOptions.ProxyCreationEnabled設置爲false。這可以防止EF爲您的POCO對象創建代理。第二個是指示服務器端的WCF DataContractSerializer使用ProxyDataContractResolver作爲POCO的序列化。

第二個選項可以在http://msdn.microsoft.com/en-us/library/ee705457.aspx找到。由於我剛剛發現這些解決方案,我不能說我會推薦哪種解決方案作爲一般慣例,儘管我傾向於後者,因爲EF查詢可能會被其他調用者不時重複使用,可能希望返回對象與適當的EF代理。無論如何,我知道這個問題已經晚了,但我希望能幫助那些遇到這個問題的人。

+0

謝謝,使用第一個解決方案,非常有幫助 – Dzmitry 2011-10-04 18:29:32

+0

感謝您的信息,真的很有幫助 – 2013-06-20 11:59:56

3

它的.INCULDE在你的LINQ陳述中。

我相信這樣做的原因是由於無限的數據結構指向和從「一邊」到您的關係「多」一邊。

這可以通過展開你的數據結構,在調試器的.INCLUDE查詢語句的結果設置一個斷點觀察...

觀察: 訂單 - >許多產品,每一個產品 - >訂單 - >許多產品等等

我想wcf跑到那裏,並得到cought在那。

爲了打破這條產業鏈,你可以簡單地避免通過增加ignoreDataMember屬性

在你們的關係的許多邊......在你的情況下,產品指向回到您的數據傳輸對象 .. ...

[IgnoreDataMember] public Order OrderFatherElement {get;組; }

這種方式達到這一childnode

@microsoft時WCF會停止serializingattempt ....用於修復一些潛在的?

映入眼簾,

Kieredin Garbaa