IQueryable functionality, like Include, but for a single Entity?

谁说我不能喝 提交于 2019-12-13 05:35:56

问题


I'm using Entity Framework 6, and have implemented some semblance of the repository pattern. Initially, my repositories had functions like GetAll that returned an IEnumerable to avoid leaking the data layer abstractions out too much. But, my service layer, which is a wrapper around my repositories and contains business logic, needed more control over the queries. Control such as eager loading of related entities, selecting only certain columns, etc. So, in trying to avoid just exposing the DbContext to my service layer, I adjusted the repositories so that they now return IQueryable so that the service layer can do things like chain Includes onto the query, etc.

Problem is that my repositories have a method for returning a single entity, and the function just returns the POCO for the entity. These are the most likely functions for needing eager loading, calling Include. Can't do that off the POCO, obviously.

Is there something like IQueryable for a single entity for additional chaining of Include logic etc? Or a way to adjust this logic to allow for that? An example of a repository of mine is this:

namespace Portal.Repositories
{
    public class UploadRepository : IUploadRepository
    {
        private readonly IPortalContext m_context;

        public UploadRepository(IPortalContext context)
        {
            m_context = context;
        }

        #region Methods

        public int Count(Expression<Func<Upload, bool>> predicate)
        {
            return m_context.Uploads.Count(predicate);
        }

        public Upload Get(Expression<Func<Upload, bool>> predicate)
        {
            return m_context.Uploads.FirstOrDefault(predicate);
        }

        public Upload Insert(Upload entity)
        {
            return m_context.Uploads.Add(entity);
        }

        public Upload Delete(Upload entity)
        {
            return m_context.Uploads.Remove(entity);
        }

        public IQueryable<Upload> All()
        {
            return m_context.Uploads;
        }

        public IQueryable<Upload> Where(Expression<Func<Upload, bool>> predicate)
        {
            return m_context.Uploads.Where(predicate);
        }

        #endregion
    }
}

You can see my Get method, and how it's not possible for my services to pick and choose when to Include or not to, because it just returns a POCO.


回答1:


You can add some functionality to your repositories to pass some include expressions.

using System.Data.Entity;

namespace Portal.Repositories
{
  public class UploadRepository : IUploadRepository
  {
    public Upload Get(
      Expression<Func<Upload, bool>> predicate, 
      params Expression<Func<Upload, object>>[] includeExpressions)
    {
      var uploads = m_context.Uploads;
      foreach (var i in includeExpressions)
        uploads = uploads.Include(i);
      return uploads.FirstOrDefault(predicate);
    }
  }
}



回答2:


How about this:

public List<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
                         Func<IQueryable<TEntity>, IOrderedEnumerable<TEntity>> orderBy = null,
                                     string includeProperties = "")
    {
        IQueryable<TEntity> query = DbSet;
        if (filter != null)
        {
            query = query.Where(filter);
        }

        query = includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Aggregate(query, (current, includeProperty) => current.Include(includeProperty));

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

[Edit]: This is what I currently am using in my own code. You need to change and adjust the code to fit your purpose but the idea is to pass the Include properties as a comma separated value down to your Get function.



来源:https://stackoverflow.com/questions/19665887/iqueryable-functionality-like-include-but-for-a-single-entity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!