So been a while since I posted last, and I’m sure everyone has been worried. Turns out that I’ve been banging my head against the wall named MVC. And man I have a slew of new posts back logged for when I have more time. However, due to the new project I’ve been working one, I forced myself to tackle Lazy Loading in the Entity Framework. Turns out the solution isn’t that hard since it has everything needed to make it work.
One of the biggest waaaaahbumlance calls is the fact that Entity Framework doesn’t have lazy loading. This isn’t true. It does, you just have to do a little work, which is to be expected from a FRAMEWORK. Now I have to admit, I wish there were a slightly less odd way of doing this, but eh it’s not too bad.
Say you have a class named Topic and it has a reference to a Forum class named ParentForum. Now this is just a property on the actual class created by the E-Work to represent a many to one foriegn key relationship between the Topic table and the Forum table. Now the problem comes in when you try to use something from that property like:
Int32 someInt = topic.ParentForum.ForumId;
If you didn’t use the Include method when you got that topic:
context.Include("ParentForum").Select(topic => topic);
You are screwed because the ParentForum property will return a null. So this forces you to use Include every time you want to get a Topic and access it’s ParentForum property. Sucks.
So next thought is to find out how to lazy load and then plunk it into that generated property. Eh I don’t know about you, but that sounds like a bad idea to mess around with a generated file. You have no idea when the E-Work will just trash the file and rebuild.
Next thought was to create a proxy property to check the real one and then load if it’s not already loaded. Something like:
public Forum ParentForumLazyLoaded { get { //check and return } }
Ok so that’s not horrible except two things: The name looks dumb and people can still get at the original ParentForum property.
So in comes my solution and it’s pretty simple. Rename the property name on the class to something ParentForumInner and make it private.
Then you can create a much nicer outward facing property like:
public Forum ParentForum { get { if (!ParentForumInnerReference.IsLoaded) { ParentForumInnerReference.Load(); } return ParentForumInner; } set { ParentForumInner = value; } }
Now one of the issues with this is that although outside the class only the ParentForum property can be seen, within the class they both can be seen which can lead to issues like:
context.Topics.Where(topic => topic.ParentForum.ForumId == id); //boom
Where you should be using:
context.Topics.Where(topic => topic.ParentForumInner.ForumId == id); //yay
E-Work doesn’t know how to handle that situation when evaluating that expression and the kicker is that it does just fine compile time. You won’t know this is bad until runtime.
Other issue is that you have to do a little more work then just some setting on the property which is what most people wish for. I guess that may be true, but again this is a framework. It gives you all the tools you need to makes things work, you just have to do some coding.
The plus side to this is that with minimal coding, you can completely get rid of Include which to me is huge.