• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >ASP.NET > 解析ABP框架中的事务处理和工作单元

解析ABP框架中的事务处理和工作单元

作者:阳光铭睿 字体:[增加 减小] 来源:互联网 时间:2017-05-11

阳光铭睿通过本文主要向大家介绍了abp框架,abp框架源码,abp框架是什么,abp 263,苏泊尔vj28abp01等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

通用连接和事务管理方法
连接和事务管理是使用数据库的应用程序最重要的概念之一。当你开启一个数据库连接,什么时候开始事务,如何释放连接...诸如此类的。

正如大家都知道的,.Net使用连接池(connection pooling)。因此,创建一个连接实际上是从连接池中取得一个连接,会这么做是因为创建新连接会有成本。如果没有任何连接存在于连接池中,一个新的连接对象会被创建并且添加到连接池中。当你释放连接,它实际上是将这个连接对象送回到连接池。这并不是实际意义上的释放。这个机制是由.Net所提供的。因此,我们应该在使用完之后释放掉连接对象。这就是最佳实践。

在应用程序中,有两个通用的方来创建/释放一个数据库连接:

第一个方法:在Web请求到达的时候,创建一个连接对象。(Application_BeginRequest这个位于global.asax中的事件),使用同一个连接对象来处理所有的数据库操作,并且在请求结束的时候关闭/释放这个连接 (Application_EndRequest事件)。

这是个简易但却没效率的方法,原因:

  • 或许这个Web请求不需要操作数据库,但是连接却会开启。这对于连接池来说是个毫无效率的使用方式。
  • 这可能会让Web请求的运行时间变长,并且数据库操作还会需要一些执行。这也是一种没效率的连接池使用方式。
  • 这对于Web应用来说是可行的。如果你的应用程序是Widnows Service,这可能就无法被实现了。
  • 同样的这是一个使用事务式的数据库操作最佳场景。如果有一个操作发生失败,所有的操作都会回滚。因为事务会锁住数据库中的一些数据列(事件数据表),它必定要是短暂的。

第二个方法: 创建一个连接当需要的时候(只要在使用它之前)并且释放它在使用它之后。这是相当高效的,但是就得乏味而且反复的去进行(创建/释放连接)。

ABP的连接和事务管理
ABP综合上述两个连接管理的方法,并且提供一个简单而且高效的模型。

1.仓储类(Repository classes)

仓储是主要的数据库操作的类。ABP开启了一个数据库连接并且在进入到仓储方法时会启用一个事务。因此,你可以安全地使用连接于仓储方法中。在仓储方法结束后,事务会被提交并且会释放掉连接。假如仓储方法抛出任何异常,事务会被回滚并且释放掉连接。在这个模式中,仓储方法是单元性的(一个工作单元unit of work)。ABP在处理上述那些动作都是全自动的。在这里,有一个简单的仓储:

public class ContentRepository : NhRepositoryBase<Content>, IContentRepository
{
  public List<Content> GetActiveContents(string searchCondition)
  {
    var query = from content in Session.Query<Content>()
          where content.IsActive && !content.IsDeleted
          select content;

    if (string.IsNullOrEmpty(searchCondition))
    {
      query = query.Where(content => content.Text.Contains(searchCondition));
    }

    return query.ToList();
  }
}

 </div>

这个示例使用NHibernate作为ORM框架。如上所示,不需要撰写任何数据库连接操作(NHibernate中的Session)的程序代码。

假如仓储方法调用另一个仓储方法(一般来说,若工作单元方法调用另一个工作单元的方法),都使用同一个连接和事务。第一个被调用到的仓储方法负责管理连接和事务,而其余被它调用的仓储方法则只单纯使用不管理。

2.应用服务(Application service classes)

一个应用服务的方法也被考虑使用工作单元。如果我们拥有一个应用服务方法如下:

public class PersonAppService : IPersonAppService
{
  private readonly IPersonRepository _personRepository;
  private readonly IStatisticsRepository _statisticsRepository;

  public PersonAppService(IPersonRepository personRepository, IStatisticsRepository statisticsRepository)
  {
    _personRepository = personRepository;
    _statisticsRepository = statisticsRepository;
  }

  public void CreatePerson(CreatePersonInput input)
  {
    var person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };
    _personRepository.Insert(person);
    _statisticsRepository.IncrementPeopleCount();
  }
}

 </div>

在CreatePerson方法中,我们新增一个person使用person仓储并且使用statistics仓储增加总people数量。两个仓储共享同一个连接和事务于这个例子中,因为这是一个应用服务的方法。ABP开启一个数据库连接并且开启一个事务于进入到CreationPerson这个方法,若没有任何异常抛出,接着提交这个事务于方法结尾时,若有异常被抛出,则会回滚这个事务。在这种机制下,所有数据库的操作在CreatePerson中,都成了单元性的了(工作单元)。

3.工作单元(Unit of work)

工作单元在后台替仓储和应用服务的方法工作。假如你想要控制数据库的连接和事务,你就需要直接操作工作单元。下面有两个直接使用的示例:

首要且最好的使用UnitOfWorkAttribute的方式如下:

[UnitOfWork]
public void CreatePerson(CreatePersonInput input)
{
  var person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };
  _personRepository.Insert(person);
  _statisticsRepository.IncrementPeopleCount();
}
</div>

因此,CreatePerson方法转变成工作单元并且管理数据库连接和事务,两个仓储对象都使用相同的工作单元。要注意,假如这是应用服务的方法则不需要添加UnitOfWork属性,见工作单元方法:第三章,3.3.5。

第二个示例是使用IUnitOfWorkManager.Begin(...)方法如下所示:

 public class MyService
{
  private readonly IUnitOfWorkManager _unitOfWorkManager;
  private readonly IPersonRepository _personRepository;
  private readonly IStatisticsRepository _statisticsRepository;

  public MyService(IUnitOfWorkManager unitOfWorkManager, IPersonRepository personRepository, IStatisticsRepository statisticsRepository)
  {
    _unitOfWorkManager = unitOfWorkManager;
    _personRepository = personRepository;
    _statisticsRepository = statisticsRepository;
  }

  public void CreatePerson(CreatePersonInput input)
  {
    var person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };

    using (var unitOfWork = _unitOfWorkManager.Begin())
    {
      _personRepository.Insert(person);
      _statisticsRepository.IncrementPeopleCount();

      unitOfWork.Complete();
    }
  }
}

你可以注入并且使用IUnitOfWorkManager,如上所示。因此,你可以创建更多的有限范围 (limited scope)的工作单元。在这个机制中,你通常可以手动调用Complete方法。如果你不调用,事务会回滚并且所有的异常都不会被储存。Begin方法被重写从而设置工作单元的选项。</div>

这很棒,不过除非你有很好的理由,否则还是少用UnitOfWork属性。

工作单元
1.禁用工作单元(Disabling unit of work)

你或许会想要禁用应用服务方法的工作单元(因为它默认是启用的)。要想做到这个,使用UnitOfWorkAttribute的IsDisabled属性。示例如下:

[UnitOfWork(IsDisabled = true)]
public virtual void RemoveFriendship(RemoveFriendshipInput input)
{
  _friendshipRepository.Delete(input.Id);
}
</div>

 平常时, 你不会需要这么做,这是因为应用服务的方法都应该是单元性且通常是使用数据库。在有些情况下,你或许会想要禁用应用服务的工作单元:

(1)你的方法不需要任何数据库操作且你不想要开启那些不需要的数据库连接
(2)你想要使用工作单元于UnitOfWorkScope类的有限范围内,如上所述
注意,如果工作单元方法调用这个RemoveFriendship方法,禁用被忽略且它和调用它的方法使用同一个工作单元。因此,使用禁用这个功能要很小心。同样地,上述程序代码工作的很好,因为仓储方法默认即为工作单元。

2.无事务的工作单元(Non-transactional unit of work)

工作单元默认上是具事务性的(这是它的天性)。因此,ABP启动/提交/回滚一个显性的数据库等级的事务。在有些特殊案例中,事务可能会导致问题,因为它可能会锁住有些数据列或是数据表于数据库中。在此这些情境下, 你或许会想要禁用数据库等级的事务。UnitOfWork属性可以从它的建构子中取得一个布尔值来让它如非事务型工作单元般工作着。示例为:

 [UnitOfWork(false)]
public GetTasksOutput GetTasks(GetTasksInput input)
{
  var tasks = _taskRepository.GetAllWithPeople(input.AssignedPersonId, input.State);
  return new GetTasksOutput
      {
        Tasks = Mapper.Map<List&l



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • ABP框架中导航菜单的使用及JavaScript API获取菜单的方法
  • 解析ABP框架中的数据传输对象与应用服务
  • ABP框架中的日志功能完全解析
  • 详解ABP框架的参数有效性验证和权限验证
  • 解析ABP框架中的事务处理和工作单元
  • 详解ABP框架中的数据过滤器与数据传输对象的使用
  • 解析ABP框架领域层中的实体类与仓储类
  • 详解ABP框架中Session功能的使用方法
  • ABP框架的基础配置及依赖注入讲解
  • ABP框架的体系结构及模块系统讲解

相关文章

  • 2017-05-11ASP.NET MVC运行出现Uncaught TypeError: Cannot set property __MVC_FormValidation of null的解决方法
  • 2017-05-11asp.net Context.Handler 页面间传值方法第1/2页
  • 2017-05-11ASP.NET MVC数组模型绑定详解
  • 2017-05-11ASP.NET通过分布式Session提升性能
  • 2017-05-11理解HttpHandler,并为所有*.jpg图片生成一段文字于图片上
  • 2017-05-11Asp.net获取服务器指定文件夹目录文件并提供下载的方法
  • 2017-05-11引用全局程序集缓存内的程序集的方法
  • 2017-05-11asp.net 点击按钮提交后使按钮变灰不可用
  • 2018-08-20ASP.NET MVC下Bundle的使用方法
  • 2017-05-11几个 ASP.NET 小技巧

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • asp.net ext treepanel 动态加载XML的实现方法
    • ASP.NET笔记之 Request 、Response 与Server的使用
    • asp.net异步获取datatable并显示的实现方法
    • asp.net分页功能实现
    • mysql安装后.net程序运行出错的解决方法
    • ASP.NET(C#) 定时执行一段代码
    • C# Quoted-Printable编码、解码
    • Asp.net程序优化js、css实现合并与压缩的方法
    • 在ASP.NET 2.0中操作数据之三十四:基于DataList和Repeater跨页面的主/从报表
    • VS2012/VS2013本地发布网站步骤详解

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有