My question relates to the stratification in the solution I'm working on now. I get the feeling that the path I am following violates the separation of layers and would like to get some feedback from it.
My current project is an ASP.NET MVC4 application that uses autofac, EF 5.0 Code First.
I have the following layers: Domain, Data, Services and Presentation
The data layer uses a repository that returns results from the database through EntityFramework. This repository returns an IQueryable <> object as a set of results. (This is because DbSet <> EF is derived from IQueryable <>).
public interface IRepository<T> where T : BaseEntity { T GetById(object id); void Insert(T entity); void Update(T entity); void Delete(T entity); IQueryable<T> Entities { get; } }
The service layer uses the specified repository and thus works with IQueryable <> objects. By default, I used my service methods to return IEnumerbale <> objects for data recovery, so my view level should always get the IEnumerable <> collection from the service.
Hopefully the context is clear enough. That's my problem:
I have the following two domain classes:
public class Video { public virtual string Title { get; set; } public virtual VideoCategory VideoCategory { get; set; } public int VideoCategoryId { get; set; } } public class VideoCategory { public string Title { get; set; } public string Description { get; set; } public List<Video> Videos { get; set; } public VideoCategory() { Videos = new List<Video>(); } }
In addition, I have the following VideoCategoryModel class defined at my presentation level, which I need to bind in ui:
public class VideoCategoryModel { public string Title { get; set; } public string Description { get; set; } public int VideoCount { get; set; } }
As you can see, I would like to get a collection of objects representing categories of videos, with the number of videos of each category. Of course, I want to do this without selecting all the Video objects. To do this, the service method returns an IQueryable <VideoCategory> to my presentation so that I can request it the same way in my controller:
var convertedResults = from videoCategory in service.GetVideoCategories() select new VideoCategoryModel() { Title = videoCategory.Title, Description = videoCategory.Description, VideoCount = videoCategory.Videos.Count };
This query will be well interpreted by EF, which will run a good, fast Select query in the database, with the count instead of retrieving all the Video objects. This is the implementation of GetVideoCategories:
public IQueryable< VideoCategory > GetVideoCategories() { return videoCategoryRepository.Entities; }
I would like to know if I am violating my separation of problems and bundles by returning IQueryable <VideoCategory> (actually EF DbSet) directly to my controller, instead of returning List <> objects.
In addition, after calling the ToList () method in the IQueryable <object, it will not be possible to get an EF graph that translates perfectly to SQL, so again I cannot return List <VideoCategory> from the service.
So, to summarize the question. Is returning EFDbSet directly to the controller a good idea? Am I breaking layer separation? What are my alternatives if so.
Thanks.