Introduction
When we try to return back collection entity from WCF method then common cause comes
"The-underlying-connection-was-closed--The-connection-closed-unexpectedly"
Using the code
Entity Framework 4 enables
lazy loading of entities by default. I’m not going to argue about whether that
is good or bad, but there is something you should be aware of. If you’re like
me, then over the years you’ll have learned that most classes that implement
IDisposable should be used using a ‘using’ statement. This is especially true
if you’re connecting to a database. So using Entity Framework your code may
look something like this:
List<SModule> lst_smodule =new List<SModule>() ;
using (COSMOSDBEntities en = new COSMOSDBEntities())
<p class=" ">{
lst_smodule= (from smodule_tmp in en.SModule Select smodule_tmp).ToList();
</p><p class=" "> return lst_smodule;
</p><p class=" ">}
<span class="Apple-style-span" style="background-color: rgb(255, 255, 255); ">
<span class="Apple-style-span" style="font-size: 12px; "></span></span>
</p><p class=" "><span class="Apple-style-span" style="background-color: rgb(255, 255, 255); "><span class="Apple-style-span" style="font-size: 12px; ">This code is work fine and return Smodule information, but suppose Smodule entity have relationship with any other entity eg. SModuleUnit (via SmoduleID property). The SModuleUnit not get loaded because en.LazyLoadingEnabled is true(by default)</span></span>
</p>
This code is work fine and return Smodule information, but suppose Smodule entity have relationship with any other entity eg. SModuleUnit (via SmoduleID property). The SModuleUnit not get loaded because en.LazyLoadingEnabled is true(by default) Now suppose the above code is part of a WCF operation.
The WCF operation want to return the SModule to the caller.
Here is what happens: When WCF starts serializing the SModule object it sees the SmoduleUnit property
and will try to access the property, since it setup to do lazy loading it will now go back to the database to load the department row.
BUT hold on, the ‘using’-statement has already disposed of the object context and closed the database connection.
What is the error that you’ll see? Well it starts with a
"CommunicationException: The underlying connection was closed: The connection closed unexpectedly."
This may throw you off and make you look for a WCF issue, but you’ll be looking in the wrong area. The actual cause of the error is on the server and the fact that the ObjectContext has been disposed yet is being used.
One solution would be to increase the lifespan of the object context and not dispose of it. This, to me, feels wrong. So instead I’ll just disable lazy loading.This can be done in the code:
<span class="Apple-style-span"> List<SModule> tblMTItem =new List<SModule>() ;
using (COSMOSDBEntities en = new COSMOSDBEntities())
{
en.ContextOptions.LazyLoadingEnabled = false;
var tblMenuTemplate = (from mt in en.MenuTemplates
where mt.UserLoginID == user.UserLoginID
select mt.MenuTemplateID).ToList();
tblMTItem = (from mtItems in en.MTItems
where tblMenuTemplate.Contains(mtItems.MenuTemplateID)
select mtItems.SModuleUnit.SModule).ToList<SModule>();
return tblMTItem;
</span><span class="Apple-style-span">
}
</span>
}
Note: I’m note sure why lazy loading enabled is set to ‘True’ by default (but it is on my machine). According to the documentation
(http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontextoptions.lazyloadingenabled(VS.100).aspx)
it should default to false.