0

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

所以我决定使用GenericRepositoryand 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) { }
    }

这个想法是在Customer此处添加显式用于实体的方法。我不确定这是否正确,尤其是我调用构造函数的方式。但是,为不同实体添加这些特定方法的自然方法是什么?我什至不介意后退一步以更好地实施它,但我不想匆忙,因为我尝试过,目前整个概念对我来说太复杂了,我想确保我理解这些事情我在我的代码中使用。

4

1 回答 1

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();
    }
}

Notice that GetAll() and GetBy() return a queryable. This is to allow control of when the query expression gets converted to SQL and hits the database. Usually a call to ToList() will cause this. You can then inherit from this and any custom methods can make use of these two starter methods.

Also, As a general rule of thumb, you should never do a GetAll().ToList() like you have now. If you have a zilion records you will run into problems. It is also a performance issue if you are filtering down to a few records. GetAll().ToList().Where(x => x.Id = 1) basically gets all zillion records from the db into memory, then filters it down to one. You should instead do this GetAll().Where(x => x.Id = 1).ToList().

Hope this helps you along!

于 2013-11-07T15:07:48.523 回答