实现仓储

返回总目录《一步一步使用ABP框架搭建正式项目系列教程》


这一节我们来实现上一节定义的仓储接口。

上一节是在领域层定义的仓储接口,但是需要注意的是,实现这些仓储接口是在基础设施层,在我的项目中就是EntityFramework层。这样做的好处就是领域层完全独立于基础设施层,耦合程度大大降低。

上一节我们定义了一个ICityRepository仓储接口,所以接下来我们来实现它。现在我们找到基础设施层名为“Repositories”的文件夹,在这里面存放实现仓储接口的类。这个文件夹是ABP模板自动帮我们生成的,而且可以它看到还有一个父目录EntityFramework。本目录下ABP模板已经帮我们创建了一个仓储基类“ChargeStationRepositoryBase”,以后如果我们要给仓储实现添加公共的方法时,就可以直接添加到该基类中。父目录下有一个之前讲过的数据库上下文类的子类。

image

接下来,在Repositories文件夹里定义ICityRepository的实现类CityRepository,代码如下:

namespace Noah.ChargeStation.EntityFramework.Repositories
{
    public class CityRepository:ChargeStationRepositoryBase<Cities>,ICityRepository
    {
        public CityRepository(IDbContextProvider<ChargeStationDbContext> dbContextProvider):base(dbContextProvider)
        {
            
        }
        public List<Cities> GetCitiesWithProvince(string provinceCode)
        {
            var query = GetAll();//GetAll()返回一个IQueryable<T>,我们可以通过它来查询
              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<List<Cities>> GetCitiesWithProvinceAsync(string provinceCode)
        {
            return await GetAllListAsync(c => c.ProvinceCode == provinceCode);
        }

这里注意一下GetAll()方法和GetAllList()方法的区别:前者返回的类型是IQueryable<T>,后者是List<T>。说到这里又不得不说下IQueryable<T>和List<T>的区别。

IQueryable<T>:

当你在Repository对象以外的地方调用GetAll这个方法,必定会开启数据库连接。这是因为IQueryable<T>允许延迟执行。只有在IQueryable<T>(或一些存取已查询的对象方法)上使用ToList()或foreach()迭代IQueryable<T>时,才会实际执行数据库的查询。因此,当你调用ToList方法时,数据库连接必需是启用状态。我们可以使用ABP所提供的UnitOfWork特性在调用的方法上来实现。注意,Application Service方法预设都已经是UnitOfWork。因此,使用了GetAll方法就不需要如同Application Service的方法上添加UnitOfWork特性。

List<T>:

返回的该结果说明已经执行了数据库查询或者已经从内存中取出了数据(如果内存中有的话)。

好的,今天的实现仓储就讲到这,下一次说《构建应用层服务》。

posted @ 2015-11-01 23:08  tkbSimplest  阅读(...)  评论(...编辑  收藏