Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

The Underlying Connection Was Closed: The Connection Closed Unexpectedly in EF 4.0

4.20/5 (5 votes)
8 Feb 2012CPOL2 min read 33.4K  
The Underlying Connection Was Closed: The Connection Closed Unexpectedly in EF 4.0

Introduction


When we try to return back collection entity from WCF method, then the 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())
    {
    lst_smodule= (from smodule_tmp in en.SModule Select smodule_tmp).ToList();
    
    return lst_smodule;       
}

This code works fine and returns Smodule information, but suppose Smodule entity has a relationship with any other entity eg. SModuleUnit (via SmoduleID property). The SModuleUnit not get loaded because en.LazyLoadingEnabled is true(by default).


This code works fine and returns Smodule information, but suppose Smodule entity have relationship with any other entity, e.g., SModuleUnit (via SmoduleID property). The SModuleUnit does not get loaded because en.LazyLoadingEnabled is true(by default)


Now suppose the above code is part of a WCF operation. The WCF operation wants 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 is 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:


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

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)