Let’s say I have a User Entity, and created partial User class so I can add some methods (like with NHibernate). I added GetByID to make getting user easier:
public static User GetByID(int userID)
{
using (var context = new MyEntities())
{
return context.Users.Where(qq => qq.UserID == userID).Single();
}
}
Now, somewhere in business logic I’d like to do something like this:
var user = User.GetByID(userID);
var posts = user.GetAllPostsForThisMonth();
foreach(var post in posts)
{
Console.WriteLine(post.Answers.Count);
}
GetAllPostsForThisMonth() is similar to GetByID – has context and is disposing it right after execution.
Normally I can’t do this because context is disposed when I call post.Answers.Count. This, I think, renders my methods useless… Or am I missing something? Can I anyhow use my entities like this? Or should I create method for every single query I use (like post.GetAnswersCount())? Thanks in advance!
The behavior you’re lamenting is actually good, because it keeps you from shooting yourself in the foot. If you had been allowed to do this, it would have cause
nround-trips to the database (wherenis the number of posts), and each one of those round-trips would have pulled all the data for all the Answers, when all you wanted was theCount. This could have an enormous performance impact.What you want to do is construct an object that represents all the information you expect to need from the database, and then construct a LINQ query that will actually load in all the information you expect to use.
This produces a single SQL query and, in a single round-trip, produces exactly the information you wanted without loading in a ton of information you didn’t want.
Update
If NHibernate works anything like Java’s Hibernate, it won’t do lazy loading after the context is disposed, either. Entity Framework does give you a lot of options along these lines: which one works best for you will depend on your particular situation. For example:
Here’s an example of eager loading:
However, since Entity Framework basically constitutes your "Data Access" tier, I would still argue that the best practice will be to create a class or set of classes that accurately model what your business layer actually wants out of the data tier, and then have the data access method produce objects of those types.