I have, say, a database containing tables Forums and Topics. Each topic has a foreign key to its parent forum.
Their associated C# models are Forum and Topic and Forum has an ICollection pointing to its child topics. I have a Forum repository which I use to directly access entity framework's context and I only return Forum / IEnumerable from it. The rest of the application only accesses the database through this repository. My question is the following: at some point in time, I want to get, say, all forums from the database without populating the Topics property. To do this, I'd have to have a method GetAll that'd do this: return _context.Forums.ToList();.
But now suppose that I also want at some point to return all forums, but with their Topics property populated. I guess I could create a new method in the repository (called GetAllForumsWithTopics or something), but it seems weird to create a new method every time I want to include more fields (maybe at some point I also want to include a property for the topic, say its list of Posts.. then I'd have to go like GetAllForumsWithTopicsWithPosts?).
So, I'd like to somehow define a method GetAllForums("includelist") [EDIT: I actually wouldn't like a string as the parameter, but a lambda expression :)] method that would allow me to include properties down the hierarchy (not only for the Forums themselves). What would be a good way of doing that?
Probably a good idea to write out the code you're attempting to do. The way I'm reading this is that you have something like the following:
public class Forum
{
public int Id {get; set;}
public IEnumerable<Topic> Topics {get; set;}
}
public class Topic
{
public int Id {get; set;}
public Forum Forum {get; set;}
}
There are a few ways to solve this. It sounds like you already know the difference between Virtual and Non-Virtual, when it comes to how eager it loads the contents. You can selectively include child elements using the Include property (see: https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx)
Personally, the route I'd probably approach this is in my EF implementation class (that implements an interface that's used elsewhere) to have two get methods:
public virtual IQueryable<Forum> Forums => _context.Forums;
public virtual IQueryable<Forum> ForumsWithChildren => _context.Forums.Include(m => m.Topic)
In a "real world" application of this, there should be a time limiter, and only pulling the topics by a specific forum call:
public virtual Forum GetForumWithRecentPosts(int id)
{
//Add where clause to restrict based off date.
return Forums.Where(x => x.Id == id).include(m => m.Topic);
}