栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ABP学习笔记:初步理解仓储

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ABP学习笔记:初步理解仓储

一.仓储的简单介绍

仓储(Repository):这是属于领域层的重要组成部分,它的作用就是完成和数据库的交互工作,仓储里封装了很多操作数据库的方法。一般地,一个分离的仓储用于一个实体(或者聚合根)。

一般用法:

public class InvoiceAppService:IITransientDependency
{
    private readonly IRepository _InvoiceRepository;
    public InvoiceAppService(IRepository InvoiceRepository)
    {
        _InvoiceRepository=InvoiceRepository;
    }
    public void Invoice(xxx)
    {
        InvoiceRepository.Insert(xxx);
    }
}

IRepository接口

在ABP中,一个仓储类应该实现一个IRepository接口。为每一个仓储定义一个接口是一个好的做法。

一个Person实体的仓储定义如下:

public interface IPersonRepository : IRepository

{

}

IPersonRepository扩展了IRepository,它用于定义拥有主键类型为int32的实体。如果你的实体不是int,那么可以扩展IRepository接口,如下所示:

public interface IPersonRepository : IRepository

{

}

IRepository为仓储类定义了最通用的增删改查方法,如select,insert,update和delete方法(CRUD操作)。大多数情况下,这些方法对于简单的实体是足够了。如果这些方法对于一个实体来说已经足够了,那么就没有必要为这个实体创建仓储接口和仓储类了。

注:以下请注意 切记 一定要 使用异步 方法 查询

IRepository定义了通用的方法,从数据库中检索实体。

获得单个实体

TEntity Get(TPrimaryKey id);
Task GetAsync(TPrimaryKey id);
TEntity Single(expression> predicate);
Task SingleAsync(expression> predicate);
TEntity FirstOrDefault(TPrimaryKey id);
Task FirstOrDefaultAsync(TPrimaryKey id);
TEntity FirstOrDefault(expression> predicate);
Task FirstOrDefaultAsync(expression> predicate);
TEntity Load(TPrimaryKey id);

Get方法用于获得一个给定主键(Id)的实体。如果在数据库中没有找到这个实体,就会抛出异常。Single方法和Get类似,但是它的参数是一个表达式而不是一个Id。因此,你可以使用Lambda表达式获得一个实体。样例用法:

var person = _personRepository.Get(42);

var person = _personRepository.Single(p => p.Name == "Halil İbrahim Kalkan");

注意:如果根据给定的条件没有查找出实体或者查出不止一个实体,那么Single方法会抛出异常。

FirstOrDefault是相似的,但是如果根据给的的Id或者表达式没有找到实体,那么就会返回null。如果对于给定的条件存在不止一个实体,那么会返回找到的第一个实体。

Load方法不会从数据库中检索实体,但是会创建一个用于懒加载的代理对象。如果你只用了Id属性,那么Entity实际上并没有检索到。只有你访问实体的其他属性,才会从数据库中检索。考虑到性能因素,这个就可以替换Get方法。这在NHiberbate中也实现了。如果ORM提供者没有实现它,那么Load方法会和Get方法一样地工作。

一些方法有用于async编程模型的异步(async)版本。

获得实体的列表

List GetAllList();

Task> GetAllListAsync();

List GetAllList(expression> predicate);

Task> GetAllListAsync(expression> predicate);

IQueryable GetAll();

GetAllList从数据库中检索所有的实体。该方法的重载可以用于过滤实体。例子如下:

var allPeople = _personRepository.GetAllList();

var somePeople = _personRepository.GetAllList(person => person.IsActive && person.Age > 42);

GetAll返回的类型是IQueryable。因此,你可以在此方法之后添加Linq方法。例子如下:

//Example 1

var query = from person in _personRepository.GetAll()

where person.IsActive

orderby person.Name

select person;

var people = query.ToList();


//Example 2:

List personList2 = _personRepository.GetAll().Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).Skip(40).Take(20).ToList();

有了GetAll方法,几乎所有的查询都可以使用LINQ重写。甚至可以用在一个连接表达式中。

这些方法也存在用于异步编程模型的asyn版本。

自定义返回值

也存在提供了IQueryable的额外方法,在调用的方法中不需要使用UnitOfWork。

T Query(Func, T> queryMethod);

Query方法接受一个接收IQueryable的lambda(或方法),并返回任何对象的类型。例子如下:

var people = _personRepository.Query(q => q.Where(p => p.Name.Contains("H")).OrderBy(p => p.Name).ToList());

在该仓储方法中,因为执行了给定的lambda(或方法),它是在数据库连接打开的时候执行的。你可以返回实体列表,单个实体,一个投影或者执行了该查询的其他东西。

插入

IRepository接口定义了将一个实体插入数据库的简单方法:

TEntity Insert(TEntity entity);

Task InsertAsync(TEntity entity);

TPrimaryKey InsertAndGetId(TEntity entity);

Task InsertAndGetIdAsync(TEntity entity);

TEntity InsertOrUpdate(TEntity entity);

Task InsertOrUpdateAsync(TEntity entity);

TPrimaryKey InsertOrUpdateAndGetId(TEntity entity);

Task InsertOrUpdateAndGetIdAsync(TEntity entity);

Insert方法简化了将一个实体插入数据库,并将刚刚插入的实体返回。InsertAndGetId方法返回了新插入实体的Id。如果实体的Id是自动增长的并且需要最新插入实体的Id,那么该方法很有用。InsertOrUpdate方法通过检查Id的值插入或更新给定的实体。最后,当插入或者更新之后,InsertOrUpdateAndGetId返回该实体的值。

再次注意,一定要使用异步的版本!

更新

IRepository定义了一个方法来更新数据库中已存在的实体。它可以获得要更新的实体并返回相同的实体对象。

TEntity Update(TEntity entity);

Task UpdateAsync(TEntity entity);
删除

IRepository定义了从数据库中删除一个已存在的实体的方法。

void Delete(TEntity entity);

Task DeleteAsync(TEntity entity);

void Delete(TPrimaryKey id);

Task DeleteAsync(TPrimaryKey id);

void Delete(expression> predicate);

Task DeleteAsync(expression> predicate);

第一个方法接受一个已存在的实体,第二个方法接受一个要删除的实体的Id。

最后一个方法接受一个删除符合给定条件的所有实体的方法。注意,匹配给定谓词的所有实体都会从数据库中检索到然后被删除。因此,小心使用它,如果给定的条件存在太多的实体,那么可能会造成性能问题。

也许不是所有的ORM框架都支持Async,但是Entityframework支持。如果不支持,异步仓储方法就会同步进行。比如,在EF中,InsertAsync和Insert是等效的,因为直到工作单元完成(Dbcontext.SaveChanges),EF才会将新的实体写入数据库。

仓储实现

ABP的设计独立于一个特定的ORM(对象/关系映射)框架或者访问数据库的其他技术。通过实现仓储接口,可以使用任何框架。

ABP使用NHibernate和 Entityframework实现了开箱即用的仓储。

管理数据库连接

在仓储方法中,数据库连接是没有打开的或是关闭的。ABP对于数据库连接的管理是自动处理的。

当将要进入一个仓储方法时,数据库连接会自动打开,并且事务自动开始。当仓储方法结束并返回的时候,ABP会自动完成:保存所有的更改,完成事务的提交和关闭数据库连接。如果仓储方法抛出任何类型的异常,那么事务会自动回滚并关闭数据库。这对于所有的实现了IRepository接口的类的公共方法都是成立的。

如果一个仓储方法调用了其他的仓储方法,那么它们会共享相同的连接和事务。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/776150.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号