在通用存储库中实现IDbSet

时间:2014-03-27 02:56:35

标签: c# asp.net asp.net-mvc entity-framework repository

我已关注this tutorial并已在我的项目中实施。 我做了一些更改以使更多可测试,所以我实现了接口

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    internal MyEntities context;
    internal IDbSet<T> dbSet;

    public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
    {
        return dbSet.SqlQuery(query, parameters).ToList();
    }
    ...
}
public interface IEmployeeRepository : IGenericRepository<Employee> { }   
public class EmployeeRepository : GenericRepository<Employee>, IEmployeeRepository { }
UnitOfWork中的

public class UnitOfWork : IDisposable
{
    private MyEntities context = new MyEntities();
    private IEmployeeRepository employeeRepository;

    public IEmployeeRepository EmployeeRepository
    {
        get { return employeeRepository ?? (employeeRepository = new EmployeeRepository(context)); }
    }
}

然后我无法访问GetWithRawSql()中的dbSet,因为我更改为IDbSet。 (1)如何解决这个问题?

(2)使用上述方法是否有更好的方法(没有dbSet),因为这也是失败的,因为IDbSet

unitOfWork.EmployeeRepository.dbSet.Select(c => new {    
    EmpID = c.EmployeeID,   
    FullName = (c.LastName + ", " + c.FirstName)
}).OrderBy(o => o.FullName);

感谢。

1 个答案:

答案 0 :(得分:1)

我认为这是一个糟糕的实施,这是我目前使用的一个: 这将是你的IRepository

    public interface IRepository<T> where T : class, IEntity
    {
    void Add(T item);
    void Remove(T item);
    void Update(T item);
    void Attach(T item);
    IQueryable<T> All<TProperty>(params Expression<Func<T, TProperty>>[] path);
    IQueryable<T> All(params string[] path);
    T Find(object id);
    T First(Expression<Func<T, bool>> predicate, params string[] path);
    Task<T> FirstAsync(Expression<Func<T, bool>> predicate, params string[] path);
    T First<TProperty>(Expression<Func<T, bool>> predicate, params Expression<Func<T, TProperty>>[] path);
    IQueryable<T> Where<TProperty>(Expression<Func<T, bool>> predicate, params Expression<Func<T, TProperty>>[] path);
    IQueryable<T> Where(Expression<Func<T, bool>> predicate, params string[] includes);
   }

通常你需要将实体附加到上下文中,所以我添加了Attach方法但是如果你想保持实体框架附加Seperate(并不是真的需要)来自常规IRepository你可以定义一个新的接口并调用ISqlRepository并从IRepository继承,创建两个IRepository会让它变得更加复杂,因为它会在UnitTest中产生任何问题。任何方式,如果你想分开这将是你的ISqlRespository:

 public interface ISqlRepository<T>: IRepository<T> where T:class, IEntity
 {
      void Update(T item);
      void Attach(T item);
 }

这是unitOfWork接口:

    public interface IUnitOfWork<T> where T : class, IEntity
    {
        IRepository<T> Repistory { get; }
        IRepository<TEntity> GetTypeRepository<TEntity>() where TEntity : class, IEntity;
        object GetContext();
        int Commit();
        Task<int> CommitAsync();
}

最后具体实现(没有ISqlRepository,因为我不使用它):

这是IRespository的实现:

public class SqlRepository<T>: IRepository<T> where T: class, IEntity
{
    protected readonly DbSet<T> _objectSet;
    protected ApplicationDbContext _context;

    public SqlRepository(ApplicationDbContext context)
    {
        _objectSet = context.Set<T>();
        this._context = context;
    }

    public void Add(T item)
    {
        _objectSet.Add(item);
    }

    public void Update(T item)
    {
        _context.Entry(item).State = EntityState.Modified;
    }

    public void Remove(T item)
    {
        _objectSet.Remove(item);
    }

    public T First(Expression<Func<T, bool>> predicate, params string[] path)
    {
        IQueryable<T> query = _objectSet;
        if (path != null)
        {
            path.ForeEach(i => query = query.Include(i));
        }

        return query.FirstOrDefault(predicate);
    }

    public T First<TProperty>(Expression<Func<T, bool>> predicate, params Expression<Func<T, TProperty>>[] path)
    {
        IQueryable<T> query = _objectSet;
        path.ForeEach(p => query = query.Include(p));
        return query.First(predicate);
    }

    public IQueryable<T> Where<TProperty>(Expression<Func<T, bool>> predicate, params Expression<Func<T, TProperty>>[] path)
    {
        IQueryable<T> query = _objectSet;
        path.ForeEach(p => query = query.Include(p));
        return query.Where(predicate);
    }

    public IQueryable<T> Where(Expression<Func<T, bool>> predicate, params string[] includes)
    {
        IQueryable<T> query = _objectSet;
        includes.ForeEach(i => query = query.Include(i));
        return query.Where(predicate);
    }


    public IQueryable<T> All<TProperty>(params Expression<Func<T, TProperty>>[] path)
    {
        IQueryable<T> query = _objectSet;
        if (path != null)
        {
            path.ForeEach(p => query.Include(p));
        }
        return query;
    }

    public IQueryable<T> All(params string[] path)
    {
        IQueryable<T> query = _objectSet;
        if (path != null)
        {
            path.ForeEach(p => query = query.Include(p));
        }
        return query;
    }

    public T Find(object id)
    {
        return _objectSet.Find(id);
    }

    public void Attach(T item)
    {
        T old = _objectSet.Local.FirstOrDefault(i => i.Id == item.Id);
        if (old != null)
        {
            _context.Entry<T>(old).State = EntityState.Detached;
        }
        _objectSet.Attach(item);
    }


    public System.Threading.Tasks.Task<T> FirstAsync(Expression<Func<T, bool>> predicate, params string[] path)
    {
        IQueryable<T> query = _objectSet;
        if(path != null)
        {
            path.ForeEach(i => query = query.Include(i));
        }
        return query.FirstOrDefaultAsync(predicate);
    }
}

这个单位工作:

 public class SqlUnitOfWork<T> : IUnitOfWork<T> where T : class, IEntity
{
    private ApplicationDbContext _db;
    public SqlUnitOfWork(ApplicationDbContext context)
    {
        _db = context;
    }

    public IRepository<T> Repistory
    {
        get
        {
            return new SqlRepository<T>(_db);
        }
    }

    public int Commit()
    {
        return _db.SaveChanges();
    }

    public Task<int> CommitAsync()
    {
        return _db.SaveChangesAsync();
    }

    public object GetContext()
    {
        return this._db;
    }

    public IRepository<TEntity> GetTypeRepository<TEntity>() where TEntity : class, IEntity
    {
        return new SqlRepository<TEntity>(_db);
    }
}