【问题标题】:Simple repository asp.net mvc with entity framework带有实体框架的简单存储库 asp.net mvc
【发布时间】:2016-05-23 04:41:19
【问题描述】:

我即将开始一个中小型项目。我绝不是软件架构师。但我有时会质疑我所做的每一个动作。因为我想做正确的事情。

我找到了一种实现简单存储库的方法,我想知道这是否是一种“正确”的方法。我来到了这个解决方案,因为我知道发生了什么,并且在我掌握知识之前没有考虑复杂的事情:)

来了。

工作单元

我确保将所有存储库保存在相同的 dbcontext 下。在我的 uof 中,当从控制器调用它时,我可以访问所有 repo。

public class UnitOfWork : IDisposable
{
    private ContactRepository _contactRepo;
    private ApplicationDbContext _entities;

    public UnitOfWork(ApplicationDbContext entities)
    {
        _entities = entities;
    }

    public ContactRepository ContactRepo
    {
        get
        {
            if (_contactRepo == null)
            {
                _contactRepo = new ContactRepository(_entities);
            }
            return _contactRepo;
        }
    }


    public void Save()
    {
        _entities.SaveChanges();
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _entities.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

ContactRepository

这是一个存储库的简短示例,它接收 dbcontext 并使用它来获取我想要的任何数据

   public class ContactRepository
   {
    private ApplicationDbContext _entities;

    public ContactRepository(ApplicationDbContext entities)
    {
        _entities = entities;
    }

    public IEnumerable<Contact> GetAll()
    {
        return _entities.Contacts;
    }
}

控制器

控制器的简短示例

public class ContactController : Controller
{

    UnitOfWork uow = new UnitOfWork(new ApplicationDbContext());

    public ActionResult Index()
    {
        var contacts = uow.ContactRepo.GetAll();
        return View(contacts);
    }



    protected override void Dispose(bool disposing)
    {
        uow.Dispose();
        base.Dispose(disposing);
    }
}

通过这种方式,我将可以访问我所针对的同一 dbcontext 下的所有存储库。

我知道事情可以做得更聪明/不同。例如,一个可扩展的通用 repo。但在这种情况下,我的目标是简单易懂的东西。但还是不想犯大错,如果有重大缺陷的话。

您是否发现这种通过实体框架处理数据的方式存在重大缺陷?

【问题讨论】:

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


【解决方案1】:

如果您的目标是简单的,那么只需使用实体框架,但如果您要使用存储库模式,我会鼓励您正确地使用它。

使用存储库的两个最大动机是:

  1. 您希望将 CRUD 应用程序简化到您的数据库中。这是 通过使用接口和泛型来完成
  2. 您希望能够单独测试业务逻辑 来自外部依赖项。同样,这是通过使用 接口

下面将花费您两分钟的时间来实现,但至少您知道自己做得对,因为目前您正试图以一种无效的方式实现一个伟大的模式。

通用接口:

    public interface IRepository<T>
    {
        T GetById(int id);
        IEnumerable<T> List();
        IEnumerable<T> List(Expression<Func<T, bool>> predicate);
        void Add(T entity);
        void Delete(T entity);
        void Update(T entity);
    }

通用存储库:

    public abstract class EntityBase
    {
    }

    public class DBRepository<T> : IRepository<T> where T : EntityBase
    {
        private readonly DbContext _dbContext;

        public DBRepository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public virtual T GetById(int id)
        {
            return _dbContext.Set<T>().Find(id);
        }

        public virtual IEnumerable<T> List()
        {
            return _dbContext.Set<T>().AsEnumerable();
        }

        public virtual IEnumerable<T> List(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {
            return _dbContext.Set<T>()
                   .Where(predicate)
                   .AsEnumerable();
        }

        public void Add(T entity)
        {
            _dbContext.Set<T>().Add(entity);
        }

        public void Update(T entity)
        {
            _dbContext.Entry(entity).State = EntityState.Modified;
        }

        public void Delete(T entity)
        {
            _dbContext.Set<T>().Remove(entity);
        }

工作单元:

public class UnitOfWork : IDisposable
{
    private bool disposed = false;
    private ApplicationDbContext  context = new ApplicationDbContext();

    private IRepository<Contact> _contactRepository;

    public IRepository<Contact> ContactRepository
    {
        get
        {
            if (this._contactRepository == null)
                this._contactRepository = new DBRepository<Contact>(context);
            return _contactRepository;
        }
    }

    public void Save()
    {
        context.SaveChanges();
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
                context.Dispose();
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

【讨论】:

  • 感谢您的详细解答。是的,我知道这种实现存储库的方式。我只是停留在如何用更复杂的查询扩展不同的实体:) - 我的目标是像你写的那样拥有一个 gen repo 类,以及一种单独扩展不同存储库的方法。在这个例子中,一个带有自定义查询的联系人存储库:)。我希望你能得到我要去的地方:)
  • 当你创建、更新和删除它总是通用的,这些查询没有什么“复杂”的,对于 List 操作,我通过一个表达式,这意味着你可以将任何类型的 lambda 表达式传递给这个方法,随心所欲。如果您真的想走拥有不同存储库类的路线,那么一定要做到这一点,但要像我在上面的示例中为所有常见操作所做的那样实现泛型,然后为您所谓的复杂查询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多