2010-08-19 4 views
5

어제 WCF에서 어제 시작한 새내기.Entity Framework 오류가있는 WCF 파트 2

데이터에 Northwind를 사용하고 있으며 고객, 주문, 주문 세부 정보 및 제품 만 모델에 추가 했으므로 멋진 것은 아닙니다.

응용 프로그램을 시작하고 Test를 호출하고 중단 점을 설정하면 제품에 대한 값이 있으며 오류없이 완료됩니다. GetMaxQuantityByOrderID (10248)를 호출하려고하면 맨 아래에 오류가 표시됩니다. 왜 Test()가 작동하고 동일한 메소드 WITHIN Test()가 작동하지 않습니까? 나는 정확히 또 다른 (Test1()을 테스트와 똑같이 추가했다. 문자열 : x.ProductName을 반환한다. 정확히 Queso Cabrales를 표시한다). 다른 메서드 내에서 호출되는 메서드가 작동하지만 직접 호출하면 예외가 발생한다는 것이 이상하게 보입니다.

IEnumerable GetOrders()는 .ToList()를 추가 할 때만 작동한다는 또 다른 문제가 있습니다. (또는 .AsEnumerable()을 사용하지 않으면) 지연로드가 False으로 설정되어 있어도 오류가 발생합니다 (ObjectContext 인스턴스가 삭제되어 더 이상 연결이 필요한 작업에 사용할 수 없습니다.)). 이 논리 뒤에있는 논리는 무엇입니까?

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의 두 번째 문제는 deffered 실행 때문입니다. Btw. IQueryable <T>과 IEnumerable <T>의 차이점을 이해하고 있습니까? GetOrders 메서드가 모든 주문, 관련 고객 및 제품을 메모리에로드한다는 것을 알고 계십니까? 단일 주문을 선택하려는 경우에도 여전히 서비스에서 모든 주문을로드합니다.

편집 :

WCF 추적은 서비스 나 클라이언트를 실행하는 동안 무슨 일이 생긴 무엇을 보여줍니다 - 그것은 WCF 내부를 추적하며 WCF 개발을위한 필수적인 도구입니다. WCF 추적에 대한 자습서 및 trace viewer.

IQueryable은 데이터베이스 쿼리로 컴파일되는 식 트리를 빌드하므로 컨텍스트 범위 외부에서 해당 쿼리 (실행이 정의되지 않음)를 실행할 수 없습니다 (컨텍스트는 데이터베이스 연결을 담당합니다). 방법을 다시 작성해야합니다. 귀하의 경우 각 방법은 완전한 쿼리를 작성하고 컨텍스트 범위 내에서 해당 쿼리를 실행해야합니다. 쿼리 실행은 FirstOrDefault()와 같은 단일 레코드를 선택하거나 목록으로 변환하여 수행됩니다.

+0

, 나는 ObjectContext는 인스턴스가 배치 된 오류가 더 이상 연결을 요구하는 작업에 사용할 수 없습니다. WCF 서비스를 수행하는 적절한 방법은 무엇입니까? 나는 추적을 구성하는 것이 내가 무엇을 할 수 있는지 이해할 수 없다. 제가 말씀 드렸다시피, 저는 방금 2 일 전에 WCF에서 시작했습니다. –

+0

추적 및 EF에 대한 정보를 추가했습니다. –

+0

이 문제는 WCF 테스트 클라이언트에서만 발생합니다. 클라이언트를 사용하지 않고 결과에 asp.net 페이지를 사용하면 작동합니다. –

8

나는 당신과 아주 비슷한 문제가있었습니다. POCO 클래스를 감싸는 Entity Framework 프록시는 기본적으로 클라이언트가 EF 프록시 래퍼를 인식하지 못하기 때문에 클라이언트 측에서 직렬화를 해제 할 수없는 WCF 직렬기에 의해 직렬화된다는 것을 알게되었습니다. 내가 찾은 두 가지 해결책이있었습니다. 첫 번째는 ContextOptions.ProxyCreationEnabled를 false로 설정하는 것입니다. 이렇게하면 EF가 POCO 개체에 대한 프록시를 만들지 않습니다. 두 번째는 서버 측의 WCF DataContractSerializer가 ProxyDataContractResolver를 사용하여 POCO로 직렬화하도록 지시하는 것입니다.

두 번째 옵션은 http://msdn.microsoft.com/en-us/library/ee705457.aspx입니다. 이 솔루션을 발견 한 이래로 EF 쿼리는 다른 호출자가 때때로 다시 객체를 반환하기를 원할 수도 있으므로 EF 쿼리를 다시 사용할 수 있기 때문에 일반적인 방법으로 추천 할 수는 없습니다. 적절한 EF 대리인과 어쨌든이 질문에 늦었다는 것을 알고 있습니다.하지만이 문제를 아는 다른 사람들을 돕기를 바랍니다.

+0

감사합니다. 첫 번째 해결책을 사용하고 대단히 도움이됩니다. – Dzmitry

+0

정보를 제공해 주셔서 감사합니다. –

3

LINQ-Statement의 .Inculde.

나는이 이유가 근본적으로 결과의 무한한 데이터 구조가 "한쪽"에서 "많은"관계로 향하는 것이라고 믿습니다.

디버거에 .Include 쿼리 문의 결과에 중단 점을 설정, 당신의 자료 구조를 전개하여 관찰 할 수있는이

...

관측 : 주문 -> 많은 제품, 각 제품 -> 주문 -> 많은 제품 등등

나는 wcf가 그것으로 runns를 추측한다.

당신은 단순히 피할 수 있습니다,이 체인을 깰하여 ignoreDataMember이 관계의 많은 측에서

속성 추가 ... 귀하의 경우 제품에 의해 다시 데이터 전송 객체 에서 가리키는 .. ..

[IgnoreDataMember] public Order OrderFatherElement {get; 세트; }

그 childNode에

@microsoft에 도달 할 때 WCF는 serializingattempt 중지됩니다 이런 식으로 .... 수정에 대한 몇 가지 가능성? 내가 된 IQueryable로 변경하는 경우

접견,

Kieredin Garbaa