返回总目录《一步一步使用ABP框架搭建正式项目系列教程》
这一节我们来实现上一节定义的仓储接口。
上一节是在领域层定义的仓储接口,但是需要注意的是,实现这些仓储接口是在基础设施层,在我的项目中就是EntityFramework层。这样做的好处就是领域层完全独立于基础设施层,耦合程度大大降低。
上一节我们定义了一个ICityRepository仓储接口,所以接下来我们来实现它。现在我们找到基础设施层名为“Repositories”的文件夹,在这里面存放实现仓储接口的类。这个文件夹是ABP模板自动帮我们生成的,而且可以它看到还有一个父目录EntityFramework。本目录下ABP模板已经帮我们创建了一个仓储基类“ChargeStationRepositoryBase”,以后如果我们要给仓储实现添加公共的方法时,就可以直接添加到该基类中。父目录下有一个之前讲过的数据库上下文类的子类。
接下来,在Repositories文件夹里定义ICityRepository的实现类CityRepository,代码如下:
namespace Noah.ChargeStation.EntityFramework.Repositories { public class CityRepository:ChargeStationRepositoryBase,ICityRepository { public CityRepository(IDbContextProvider dbContextProvider):base(dbContextProvider) { } public List GetCitiesWithProvince(string provinceCode) { var query = GetAll();//GetAll()返回一个IQueryable ,我们可以通过它来查询 var query2 = Context.Cities.AsQueryable();//也可以直接使用EF的DbContext对象 var query3 = Table.AsQueryable();//另一种选择:直接使用Table属性代替"Context.Cities",都是一样的。 if (!string.IsNullOrEmpty(provinceCode)) { query = query.Where(c => c.ProvinceCode == provinceCode); } return query.ToList(); } } }
CityRepository继承了泛型的ChargeStationRepositoryBase类,而且实现了仓储接口。这里要显示声明实现类的有参数的构造函数,使用泛型的IDbContextProvider将数据库上下文的子类ChargeStationContext传给父类的构造函数。
GetCitiesWithProvince(…)方法是我们实现仓储接口ICityRepository中的方法,也是我们自己特殊需要的方法。
在仓储中,我们可以自由地使用Context(EF的DbContext)对象和数据库。ABP框架为我们管理数据库连接,事务,创建和释放DbContext,因而不用我们自己处理了。
这里我们也可以定义一个异步版本的方法,功能和上面的方法相同(关于异步的博客,可以看我的目录《C#异步编程》):
public async Task> GetCitiesWithProvinceAsync(string provinceCode) { return await GetAllListAsync(c => c.ProvinceCode == provinceCode); }
这里注意一下GetAll()方法和GetAllList()方法的区别:前者返回的类型是IQueryable
IQueryable
当你在Repository对象以外的地方调用GetAll这个方法,必定会开启数据库连接。这是因为IQueryable
List
返回的该结果说明已经执行了数据库查询或者已经从内存中取出了数据(如果内存中有的话)。
好的,今天的实现仓储就讲到这,下一次说《构建应用层服务》。