您的位置  > 互联网

关于abp框架有哪些特性、有什么好处我这里就不讲了

学习路径

一年前,在博客园看到阳光明睿的一系列文章,让我对abp框架产生了兴趣。 从此开始了abp框架的探索。 后来在查找资料的过程中,发现tkb智健的博客也很不错。 他还翻译了官网的英文文档。 如果您想入门,阅读本系列文章非常好。 如果你想研究源码,可以参考本系列文章。

Abp的源代码地址是:。

框架概述

该框架版本使用的主要技术有mvc5.0、web api、EF 6.1。

1.整体框架概述

.Core:主要存储业务实体和仓储接口。

文件夹:这里有两个应用服务层。 当时我们想把读和写分开,一个读,一个写。 但底层数据访问层并没有实现读写分离。 (目前还没有找到完全实现读写分离的解决方案)

..:主要存放实体映射文件和仓储实现类。

.Web:网络界面。

.:api接口。

.:框架中与业务无关的公共类。

.WF.:处理业务相关项目。

.Abp:封装abp类的公共类。

:授时服务类库。

:一个轻量级的ORM框架。 主要添加支持EF操作包。 如果是其他数据库则可以忽略此项。 为了更好的统一,以后都应该用存储过程来代替。

零文件夹:这里面的三个项目分别对应abp的应用服务层、核心层、数据访问层。 本项目主要用于操作一些基础信息表和公共模块。 例如,用户、角色、权限、部门等。

2、整体框架设计

在整体框架设计中,我认为“模块”更为重要。 这里我谈谈我对模块的理解。 每个单独的类库或应用程序都是一个模块。 当需要使用Ioc容器、abp启动配置、或者应用程序启动时进行一些设置时,就需要使用abp中的模块。 模块类可以依赖。 模块类在应用程序启动时执行,并根据依赖关系执行。 也就是说,不依赖的模块最后执行。 该模块有四个方法,()、()、()、()。 前三个方法在应用程序启动时运行,最后一个方法在应用程序关闭时运行。 模块方法的执行顺序是先执行所有模块的(),然后执行所有模块的(),最后执行所有模块的()。

整体框架模块的依赖设计图如下:

3. 框架详细设计

这个框架的总体思路是基于abp的示例代码。 我只是在原有框架的基础上做了一些扩展。 同样的框架设计我就不说了。 谈谈差异。 该框架中的 Zero 项目与官方的 Abp.Zero 不同。 Abp.Zero 基本上提供了抽象类。 要具体实例化它们,必须继承相应的业务类库才可以使用。 该框架中的零项目直接对外提供服务接口。 .0是应用服务接口。 .Zero.Core存放实体仓储接口。 .zero..是数据访问抽象层,该类库中有继承的抽象类。 由于使用的是这个框架,对于自增类型的EF操作目前还没有解决方案。 因此,目前插入数据时的解决方案是先获取序列,然后再插入数据。

获得序列有两种解决方案。 一种是向存储库的基类添加公共方法。 这种方案的优点是可以很好的集成依赖注入,并且可以实现事务控制。 但这种方案的缺点是所有的实体类都必须有对应的存储基类。 另一种选择是添加新的数据访问。 这种方案的优点是可以在应用服务的基类中添加一个公共方法来获取序列。 缺点是序列获取和其他数据操作不能一起接受事务控制。

我使用框架中的第二种解决方案。 总体思路是在.Zero..项目中添加一个接口,该接口有两种获取序列的方法。 在..项目中添加,该类继承了接口,并且有一个用于访问数据库的变量。 为什么要这样设计呢? 因为脱钩。 Zero中的所有项目都不需要直接引用具体的对象,而只需要引用接口。 具体的接口实现是在运行时注入的。 具体代码如下:

 1  public interface IDbContextHelper
 2     {
 3         /// 
 4         /// 获取序列值
 5         /// 
 6         /// 
 7         /// 
 8         /// 
 9         T GetSequenceValueByName(string sequenceName) where T : struct;
10 
11         /// 
12         /// 获取序列值(默认int)
13         /// 
14         /// 
15         /// 
16         int GetSequenceValueByName(string sequenceName);
17     }

查看代码

 1 public class DbContextHelper:IDbContextHelper,ITransientDependency
 2     {
 3         /// 
 4         /// 数据访问类
 5         /// 
 6         private volatile DbContext _dbContext ;
 7 
 8         /// 
 9         /// 锁帮助对象
10         /// 
11         private readonly object _lockObject = new object();
12 
13         /// 
14         /// 
15         /// 
16         private  DbContext TopeveryDbContext
17         {
18             get
19             {
20                 if (_dbContext == null)
21                 {
22                     lock (_lockObject)
23                     {
24                         if (_dbContext == null)
25                             _dbContext = IocManager.Instance.Resolve();
26                     }
27                 }
28                 return _dbContext;
29             }
30         }
31 
32         /// 
33         /// 得到序列的字符串
34         /// 
35         /// 
36         /// 
37         private string GetSequenceSqlByName(string sequenceName)
38         {
39             return "select " + sequenceName + ".nextval from dual";
40         }
41 
42         /// 
43         /// 获取序列值
44         /// 
45         /// 
46         /// 
47         /// 
48         public T GetSequenceValueByName(string sequenceName) where T : struct
49         {
50             string sql = GetSequenceSqlByName(sequenceName);
51             return TopeveryDbContext.Database.SqlQuery(sql).First();
52         }
53 
54 
55         /// 
56         /// 获取序列值(默认int)
57         /// 
58         /// 
59         /// 
60         public int GetSequenceValueByName(string sequenceName) 
61         {
62             return GetSequenceValueByName<int>(sequenceName);
63         }
64     }

查看代码

这就是今天的全部内容。

源码地址: