Suppose you have three tables in your database where one of them specifies a many-to-many relationship between the other two (example from AdventureWorks):

Suppose also that you have a method such as GetVendors(int productID) that will retrieve all the vendors for a given product through the ProductVendors table (that is , the many-to-many table).
Now, if this method is exposed via a WCF service, when your client calls it you will see an exception like this one:
- "System.ServiceModel.CommunicationException was unhandled. An error occurred while receiving the HTTP response to http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/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."
And the subsequent inner exception messages:
- "The underlying connection was closed: An unexpected error occurred on a receive."
- "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."
- "An existing connection was forcibly closed by the remote host"
What the ... is going on? This is a seralization problem (yes, the exception message is not that clear). To test the serialization of your data I recommend the following test (from here):
Service1 svc = new Service1();
List<Vendor> lv = svc.GetVendors(319);
object dto = lv[0];
DataContractSerializer ser = new DataContractSerializer(typeof(Vendor));
FileStream writer = new FileStream(@"C:\Temp\" + dto.GetType().Name + ".xml", FileMode.Create);
ser.WriteObject(writer, dto);
writer.Close();
When running the code above, I get a clearer exception mentioning serialization:
- "System.Runtime.Serialization.SerializationException: Object graph for type 'WcfServiceLibrary1.ProductVendor' contains cycles and cannot be serialized if reference tracking is disabled."
If you then check the XML file that this test created for the Vendor object you will see it is huge and broken. The problem is that the Vendor object contains a reference to the one or more Product objects (linked through the ProductVendor table) which contain a reference to one or more Vendors which contain references to Prodcuts and so on ... An infinite cycle of references is being created. WCF does not realize that these references point to the same object and it serializes each reference (eventually throwing an exception).
There is a great post (http://blogs.msdn.com/sowmy/archive/2006/03/26/561188.aspx) about how to preserve object references in WCF. But if you are looking for a less complicated solution you can just open the *.dbml file, right click, select 'Properties' and choose 'Seralization Mode' = 'Unidirectional'. As the name indicates, serialization only goes in one direction: from a product to a vendor but not back to products (or from a vendor to a product but not back to products).
Without unidirectional serialization you could do this:
Vendor[] vendors = svc.GetVendors(319);
foreach (Vendor v in vendors)
{
Console.WriteLine(v.Name);
foreach (ProductVendor pv in v.ProductVendors)
{
Product p = pv.Product;
foreach (ProductVendor pv2 in p.ProductVendors)
{
Vendor v2 = pv2.Vendor;
// and so on
}
}
}
With unidirectional serialization you can only get as far as this:
Vendor[] vendors = svc.GetVendors(319);
foreach (Vendor v in vendors)
{
Console.WriteLine(v.Name);
foreach (ProductVendor pv in v.ProductVendors)
{
int prodID = pv.ProductID;
}
}