GenericRepository和UnitOfWork自定义

时间:2013-11-07 13:54:03

标签: c# entity-framework-5 repository-pattern unit-of-work

我正在从头开始研究ASP.NET MVC 4项目。我决定使用Entity Framework 5Code First工作流程从数据访问层开始。我以前工作的公司使用了Repository pattern的{​​{1}}非常好的实现,包括存储库,服务,存储库和服务的抽象工厂以及Unity的{​​{1}}。我试图重做它,但它对我来说太复杂了,我花了很多时间来复制我在那里使用的东西,所以我决定做一些研究并选择更轻松的东西。

所以我决定使用DIGenericRepository - 远离最初的计划,但这是我的大多数搜索中显示的实现。所以我做了一个非常基本的实现(直到我确定我知道发生了什么,甚至可能低于我理解的能力)并且实际上我认为对于这个确切的项目它可能就够了但我想要的是能够在不同的实体上调用其他自定义方法。

我认为这从通用存储库的想法中获得了很多,但是如果我尝试使用其他实现它会变得指数级更难,所以我想知道是否有办法将其添加到我的实现中而不会伤害太多的想法在通用存储库后面。

我现在拥有的是UnitOfWork类:

GenericRepository

和我的public class GenericRepository<TEntity> where TEntity : class { internal DBContext context; internal DbSet<TEntity> dbSet; public GenericRepository(DBContext context) { this.context = context; this.dbSet = context.Set<TEntity>(); } public virtual IEnumerable<TEntity> Get() { IQueryable<TEntity> query = dbSet; return query.ToList(); } //just the standard implementation 班级:

UnitOfWork

因为您可能会看到我的public class UnitOfWork : IDisposable { private DBContext context = new DBContext(); private CustomerRepository customerRepository; public CustomerRepository CustomerRepository { get { if (this.customerRepository == null) this.customerRepository = new CustomerRepository(context); return customerRepository; } } private GenericRepository<Order> orderRepository; public GenericRepository<Order> orderRepository { get { 实体正在使用Order,但我创建了一个测试类GenericRepository以用于我的CustomerRepository实体。

现在这个班级Customer看起来像这样:

CustomerRepository

并且想法是在这里添加为public class CustomerRepository : GenericRepository<Customer> { public CustomerRepository(DBContext context) : base(context) { } } 实体明确的方法。我不确定这是否正确,尤其是我调用构造函数的方式。但是,为不同实体添加这些特定方法的自然方法是什么?我不介意甚至退后一步更好地实施它,但我不想急于它,因为我尝试过,此刻整个概念对我来说太复杂了,我想确定我理解的东西我在我的代码中使用。

1 个答案:

答案 0 :(得分:1)

我认为你走在正确的轨道上。这是我使用的通用存储库:

public interface IRepository<TEntity>
    where TEntity : class
{
    IQueryable<TEntity> GetAll();
    IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate);
    TEntity GetById(long id);
    void Add(TEntity entity);
    void Update(TEntity entity);
    void Delete(TEntity entity);
}

public class Repository<TEntity> : IRepository<TEntity>
    where TEntity : class
{
    protected readonly DbEntities Context;
    protected readonly DbSet<TEntity> Set;

    public Repository()
    {
        Context = new DbEntities();
        Set = Context.Set<TEntity>();
    }

    public virtual IQueryable<TEntity> GetAll()
    {
        return Set;
    }

    public virtual IQueryable<TEntity> GetBy(Expression<Func<TEntity, bool>> predicate)
    {
        return Set.Where(predicate);
    }

    public virtual TEntity GetById(long id)
    {
        return Set.Find(id);
    }

    public virtual void Add(TEntity entity)
    {
        Set.Add(entity);
        Context.SaveChanges();
    }

    public virtual void Update(TEntity entity)
    {
        Set.Attach(entity);
        Context.Entry(entity).State = EntityState.Modified;
        Context.SaveChanges();
    }

    public virtual void Delete(TEntity entity)
    {
        Set.Remove(entity);
        Context.SaveChanges();
    }
}


// And assuming User is a data object with an Id property:
public interface IUserSpecificRepository
{
    List<User> GetById(long id)
}

public class UserSpecificRepository : IUserSpecificRepository, Repository<User>
{
    public virtual List<User> GetById(long id)
    {
        return GetBy(x => x.Id = id).ToList();
    }
}

请注意,GetAll()GetBy()会返回可查询对象。这是为了允许控制查询表达式何时转换为SQL并命中数据库。通常,调用ToList()会导致此问题。然后,您可以从此继承,任何自定义方法都可以使用这两种启动方法。

另外,作为一般的经验法则,你不应该像现在这样做GetAll().ToList()。如果您有zilion记录,您将遇到问题。如果要过滤到几条记录,这也是一个性能问题。 GetAll().ToList().Where(x => x.Id = 1)基本上将数据库中的所有数据都记录到内存中,然后将其过滤为1。你应该这样做GetAll().Where(x => x.Id = 1).ToList()

希望这可以帮助你!