I have created a simple test solution using Entity Framework and WCF. I have only one function in the service contract, called GetAllCustomers()
that retrieves the customers from the database and returns them to the client. The client app calls the function and writes the customer names to the console.
When I call GetAllCustomers()
from the client via proxy, I get a CommunicationException
with the message,
An error occurred while receiving the HTTP response to
http://localhost:8000/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.
The inner exception is System.Net.WebException
:
The underlying connection was closed: An unexpected error occurred on a receive.
Next level of inner exception is System.IO.IOException
:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
And the final inner exception is System.Net.Sockets.SocketException
:
An existing connection was forcibly closed by the remote host
Here is the client code:
static void Main(string[] args)
{
Console.WriteLine("Press Enter to begin.");
Console.ReadLine();
ServiceReference1.Service1Client MyService = new ServiceReference1.Service1Client();
CUSTOMER[] cl = MyService.GetAllCustomers();
foreach (CUSTOMER c in cl)
{
Console.WriteLine(c.CUSTFNAME + " " + c.CUSTLNAME);
}
Console.WriteLine("Press Enter to exit.");
Console.ReadLine();
}
Here is the host application code:
static void Main(string[] args)
{
ServiceHost hostA = null;
try
{
hostA = new ServiceHost(typeof(Service1), new Uri("http://localhost:8000") );
hostA.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "Service1");
hostA.Open();
Console.WriteLine();
Console.WriteLine("Host started. Press Enter to terminate host.");
Console.ReadLine();
}
finally
{
if (hostA.State == CommunicationState.Faulted)
hostA.Abort();
else
hostA.Close();
}
}
Here is the service library code for the function:
public HashSet<CUSTOMER> GetAllCustomers()
{
var db = new TRS11Entities();
HashSet<CUSTOMER> TheCusts = new HashSet<CUSTOMER>();
foreach (CUSTOMER c in db.CUSTOMERs)
{
TheCusts.Add(c);
}
//CUSTOMER TestCust1 = new CUSTOMER();
//TestCust1.CUSTFNAME = "Joe";
//TestCust1.CUSTLNAME = "Schmoe";
//CUSTOMER TestCust2 = new CUSTOMER();
//TestCust2.CUSTFNAME = "Peter";
//TestCust2.CUSTLNAME = "Pumpkineater";
//TheCusts.Add(TestCust1);
//System.Threading.Thread.Sleep(45000);
//TheCusts.Add(TestCust2);
return TheCusts;
}
Strangely enough, if I bypass the database by replacing the foreach block with the commented out code below it, it works great!
I first thought it might be a timeout issue with the database query taking too long. However, my test code has a 45-second sleep in there, and it still returns the data to the client fine. The original code gives the exception after only about 3 seconds.
Also, if I call the original function (with the foreach block) by instantiating the WCF service directly, rather than via an endpoint/proxy, it also runs fine and returns all the customers in the database.
Lastly, I thought it might be an issue with the returned data set being too large, so I modified the foreach block and inserted a break statement after adding the first 5 customers to the results, and I still got the exception.
So, what else could be causing this?
I think the problem was that the CUSTOMER type from Entity Framework contained sets (container types) of detail records (sales, etc.), which was making the data too big. I ended up creating a new type that didn't have those, and it worked fine after that.