views:

54

answers:

1

Newbie, please bear with me as I just started yesterday with WCF.

I am using Northwind for the data and only added Customers, Orders, Order Details and Products to the model, so nothing fancy.

When I launch the application and invoke Test, and set a breakpoint, the value for products is there and it completes without error. If I then try to invoke GetMaxQuantityByOrderID(10248), I get the error listed at bottom. Why would Test() work and the same method WITHIN Test() NOT work? I even added another (Test1(), exact same as Test except it returns string: x.ProductName, which correctly displays Queso Cabrales). It seems odd that a method that is being called within another works, but calling it directly causes an exception.

Another issue I have is that the IEnumerable GetOrders() works only if I add .ToList(). Without it (or with .AsEnumerable()), I get an error (The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.), even though lazy loading is set to False. What is the logic behind this?

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;
        }
    }
}

Error:

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)
A: 

For the first issue try to turn on WCF tracing on your service. Second issue with IEnumerable is caused by deffered execution. Btw. do you understand difference between IQueryable<T> and IEnumerable<T>? Do you know that your GetOrders method loads all Orders, related Customers and Products into memory? Even if you want to select single order you still load all of them in the service.

Edit:

WCF tracing will show you what happend during service or client execution - it traces WCF internals and it is essential tool for WCF development. Tutorial on WCF tracing and trace viewer.

IQueryable builds expression tree which is compiled into database query so you can't execute that query (deffered execution) outside context scope (context is responsible for database connection). You have to rewrite your methods. In your case each method has to create complete query and execute that query inside context scope. Execution of query is performed by selecting single record (like FirstOrDefault()) or by converting to list.

Ladislav Mrnka
If I change to IQueryable, I get the error The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. What is the proper way to do WCF services? I don't understand what configuring the tracing will allow me to do. As I said, I just started with WCF 2 days ago.
Investor5555
I added some information about tracing and EF.
Ladislav Mrnka
The problem only occurs in the WCF Test Client. If I don't use the client and use an asp.net page for results, it works.
Investor5555
Than turn on WCF tracing and check why it fails in test client.
Ladislav Mrnka