当你在仓储方法外调用GetAll方法, 这必定得有一个开启状态的数据库连接,因为它返回IQueryable类型的对象。这是需要的,因为IQueryable延迟执行。它并不会马上执行数据库查询,直到你调用ToList()方法或在foreach循环中使用IQueryable(或是存取被查询结果集的情况下)。因此,当你调用ToList()方法,数据库连接必需是启用状态。示例:
[UnitOfWork] public SearchPeopleOutput SearchPeople(SearchPeopleInput input) { //Get IQueryable<Person> var query = _personRepository.GetAll(); //Add some filters if selected if (!string.IsNullOrEmpty(input.SearchedName)) { query = query.Where(person => person.Name.StartsWith(input.SearchedName)); } if (input.IsActive.HasValue) { query = query.Where(person => person.IsActive == input.IsActive.Value); } //Get paged result list var people = query.Skip(input.SkipCount).Take(input.MaxResultCount).ToList(); return new SearchPeopleOutput { People = Mapper.Map<List<PersonDto>>(people) }; }
在这里,SearchPeople方法必需是工作单元,因为IQueryable在被调用ToList()方法于方法本体内,并且数据库连接必须于IQueryable.ToList()被执行时开启。
一如GetAll()方法,如果需要数据库连接且没有仓储的情况下,你就必须要使用工作单元。注意,应用服务方法默认就是工作单元。
5.工作单元属性的限制(UnitOfWork attribute restrictions)
在下面情境下你可以使用UnitOfWork属性标签:
(1)类所有public或public virtual这些基于界面的方法(像是应用服务是基于服务界面)
(2)自我注入类的public virtual方法(像是MVC Controller和Web API Controller)
(3)所有protected virtual方法。
建议将方法标示为virtual。你无法应用在private方法上。因为,ABP使用dynamic proxy来实现,而私有方法就无法使用继承的方法来实现。当你不使用依赖注入且自行初始化类,那么UnitOfWork属性(以及任何代理)就无法正常运作。
选项
有许多可以用来控制工作单元的选项。
首先,我们可以在startup configuration中改变所有工作单元的所有默认值。这通常是用了我们模块中的PreInitialize方法来实现。
public class SimpleTaskSystemCoreModule : AbpModule
{
public override void PreInitialize()
{
Configuration.UnitOfWork.IsolationLevel = IsolationLevel.ReadCommitted;
Configuration.UnitOfWork.Timeout = TimeSpan.FromMinutes(30);
}
//...other module methods
}
方法
工作单元系统运作是无缝且不可视的。但是,在有些特例下,你需要调用它的方法。
SaveChanges:
ABP储存所有的变化于工作单元的尾端,你不需要做任何事情。但是,有些时候,你或许会想要在工作单元的过程中就储存所有变化。在这个案例中,你可以注入IUnitOfWorkManager并且调用IUnitOfWorkManager.Current.SaveChanges()方法。示例中以Entity Framework在储存变化时取得新增实体的Id。注意,当前工作单元是具事务性的,所有在事务中的变化会在异常发生时都被回滚,即便是已调用SaveChange。
事件
工作单元具有Completed/Failed/Disposed事件。你可以注册这些事件并且进行所需的操作。注入IUnitOfWorkManager并且使用IUnitOfWorkManager.Current 属性来取得当前已激活的工作单元并且注册它的事件。
你或许会想要执行有些程序代码于当前工作单元成功地完成。示例:
public void CreateTask(CreateTaskInput input) { var task = new Task { Description = input.Description }; if (input.AssignedPersonId.HasValue) { task.AssignedPersonId = input.AssignedPersonId.Value; _unitOfWorkManager.Current.Completed += (sender, args) => { /* TODO: Send email to assigned person */ }; } _taskRepository.Insert(task); }
您可能感兴趣的文章: