WCF and Entity Framework Pitfall

April 4, 2012
WCF and Entity Framework Pitfall

Recently I was tasked with creating a client application that interacted with an existing MVC Web Application. Specifically it was an Excel Add-In that would manipulate data from the same database that the Web Application used. Since we were using Entity Framework 4.1 and code first, the simplest solution for me was to just create the Data Contracts for the service on the existing models. Or so I thought.Setting everything up went very smoothly, but testing the service resulted in obscure error messages and eventually a timeout. After some painful debugging, it turned out that the Lazy Loading of Entity Framework and Serialization (WCF) do not play nicely when you have foreign keys represented as virtual child classes and many-to-many relationships.The problem is that with Lazy loading, if for example Entity A serialization accesses Entity B, Entity B is Lazy Loaded and serialized. Serialization of Entity B accesses Entity A and Entity A Lazy Loads again. This keeps repeating infinitely and is called circular lazy loading.The solution is to disable Lazy Loading at the time of each call.[sourcecode language="csharp"]dbContext.ContextOptions.LazyLoadingEnabled = false;[/sourcecode]With Lazy Loading disabled, the classes are serialized correctly for standard Entity Framework classes.Another option (that I ultimately chose) is to create separate classes as Data Transfer Objects and map them to the Entity Framework classes. If you choose the Data Transfer Object method, I highly recommend using AutoMapper. Mapping the objects with AutoMapper is extremely simple and can be accomplished in a few lines of code.[sourcecode language="csharp"]var lineItems = dbContext.LineItems.Where(li => li.QuoteId == quoteId).ToList();Mapper.CreateMap<LineItem, LineItemDto>();return Mapper.Map<List<LineItem>, List<LineItemDto>>(lineItems);[/sourcecode]AutoMapper is great for cases like mine in which the client doesn’t really need the entire entity. However, if your application does need all of the fields in each of your entity classes, then certainly disabling Lazy Loading would be worth trying first.