什么是IRepository,它有什么作用?
IRepository是实现Repository模式时使用的一个接口。它不是.NET的一部分,而是由开发人员自己创建的接口。使用Repository模式的开发人员广泛推荐使用接口进行实现。例如,在我目前开发的应用程序中,我有5个repositories,其中4个是特定的,1个是通用的。每个repository都继承自IRepository,这样可以确保在以后的开发过程中不会出现不同实现的问题。
下面是一些代码示例:
interface IRepositorywhere T : class { IQueryable Select(); }
实现一个通用repository:
public class Repository: IRepository where T : class { public IQueryable Select() { return this.ObjectContext.CreateObjectSet (); } }
实现一个特定的repository:
public class EmployeeRepository : IRepository{ public IQueryable Select() { return this.ObjectContext.Employees; } }
无论是Repository
希望这对你有所帮助。+1好的解释/代码。唯一需要补充的是我个人更喜欢让特定的repository继承通用的repository,例如public class EmployeeRepository : Repository
什么是IRepository,它的使用目的是什么?
MVC(模型-视图-控制器)推崇关注点分离,但这并不仅限于MVC层级。
数据访问本身就是一个关注点。它应该在MVC的M(模型)部分中完成。如何组织模型由你决定,但人们通常遵循经过验证的模式(为什么要重复发明轮子呢?)。存储库模式是当前的标准。然而,不要期望有一个简单的公式,因为变种几乎和开发者一样多。
IRepository只是一个你创建的接口(它不是MVC、ASP.NET或.NET的一部分)。它允许你“解耦”你的存储库与实际实现。解耦是好的,因为它意味着你的代码...:
- 你的代码更加可重用。这很好。
- 你的代码可以使用控制反转(或依赖注入)。这样做有利于保持你的关注点良好分离。这特别有用,因为它允许单元测试...
- 你的代码可以进行单元测试。在具有复杂算法的大型项目中,这特别有用。在任何地方都有好处,因为它增加了你对正在使用的技术和正在尝试在软件中建模的领域的理解。
- 你的代码围绕最佳实践构建,遵循一种常见的模式。这很好,因为它使维护变得更容易。
因此,既然你已经被解耦所吸引,那么你的问题的答案是IRepository是一个你创建的接口,并且你使你的存储库从中继承。它为你提供了一个可靠的类层次结构来使用。
我通常使用一个泛型的IRepository:
IRepository
这里的TEntity是一个实体。我使用的代码是:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Wingspan.Web.Mvc { public interface IRepository<TEntity> where TEntity : class { List<TEntity> FetchAll(); IQueryable<TEntity> Query {get;} void Add(TEntity entity); void Delete(TEntity entity); void Save(); } }
这个接口的一个具体实现可以是:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data.Linq; using Wingspan.Web.Mvc; namespace ES.eLearning.Domain { public class SqlRepository<T> : IRepository<T> where T : class { DataContext db; public SqlRepository(DataContext db) { this.db = db; } #region IRepository<T> Members public IQueryable<T> Query { get { return db.GetTable<T>(); } } public List<T> FetchAll() { return Query.ToList(); } public void Add(T entity) { db.GetTable<T>().InsertOnSubmit(entity); } public void Delete(T entity) { db.GetTable<T>().DeleteOnSubmit(entity); } public void Save() { db.SubmitChanges(); } #endregion } }
这使我可以编写以下代码:
SqlRepository<UserCourse> UserCoursesRepository = new SqlRepository<UserCourse>(db);
这里的db是一个注入到某个服务中的DataContext实例。
有了UserCoursesRepository,我现在可以在我的服务类中编写方法,例如:
public void DeleteUserCourse(int courseId) { var uc = (UserCoursesRepository.Query.Where(x => x.IdUser == UserId && x.IdCourse == courseId)).Single(); UserCoursesRepository.Delete(uc); UserCoursesRepository.Save(); }
现在,在我的控制器中,我只需编写:
MyService.DeleteUserCourse(5); MyService.Save();
使用这种模式,你的应用程序开发变得更像一个流水线,最终导致一个非常简单的控制器。流水线的每个部分都可以独立于其他部分进行测试,因此可以及早发现错误。
如果这是一个冗长而笨重的答案,那是因为真正的答案是:
购买Steven Sanderson的书《Pro ASP.NET MVC 2 Framework》并学会以MVC的方式思考。
存储库完全与MVC无关。实际上,它是由DDD(领域驱动设计)提出的。
以上设计的缺陷:只处理单个实体,不使用工作单元模式。在现实世界中,你需要在一个事务中处理多个实体,并且SaveChanges方法应该在工作单元的末尾调用,而不是在存储库类中调用。- 不使用工作单元会导致对数据库的多次往返而不是仅使用一个连接每个事务。
公平地说,如果你向“什么是IRepository”的人提出工作单元,你会让他们感到困惑。这些评论记录了超越存储库和单个实体的内容。但学习是一个迭代的过程。
只是我还是有一个坏主意,那就是把实现数据库接口的库引用到你的MVC网站中?你难道不应该把你的领域逻辑放在一个单独的库中,让它执行必要的查询到存储库,并将结果提供给请求的客户端吗?
(在此处插入IRepository文档的链接)