DDD的ABP开发框架
基于DDD的ABP开发框架初探
一、基本概念
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。
ABP是土耳其的以为架构师hikalkan开发的,现在又加入一个ismcagdas开发者。
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。
ABP的官方网站:http://www.aspnetboilerplate.com
Github上的开源项目:https://github.com/aspnetboilerplate
强烈建议从事.NET的程序员学习下。
二、技术点
1、服务端
基于最新的.NET技术 (目前是ASP.NET MVC 5、Web API 2、C# 5.0,在ASP.NET 5正式发布后会升级)
实现领域驱动设计(实体、仓储、领域服务、领域事件、应用服务、数据传输对象,工作单元等)
实现分层体系结构(领域层,应用层,展现层和基础设施层)
提供了一个基础架构来开发可重用可配置的模块
集成一些最流行的开源框架/库,也许有些是你正在使用的。
提供了一个基础架构让我们很方便地使用依赖注入(使用Castle Windsor作为依赖注入的容器,为什么没有用autofac??)
提供Repository仓储模式支持不同的ORM(已实现Entity Framework 、NHibernate、MangoDb和内存数据库)
支持并实现数据库迁移(EF 的 Code first)
模块化开发(每个模块有独立的EF DbContext,可单独指定数据库)
包括一个简单的和灵活的多语言/本地化系统
包括一个 EventBus来实现服务器端全局的领域事件
统一的异常处理(应用层几乎不需要处理自己写异常处理代码)
数据有效性验证(Asp.NET MVC只能做到Action方法的参数验证,ABP实现了Application层方法的参数有效性验证)
通过Application Services自动创建Web Api层(不需要写ApiController层了)
提供基类和帮助类让我们方便地实现一些常见的任务
使用“约定优于配置原则”
2、客户端
Bootstrap、Less、AngularJs、jQuery、Modernizr和其他JS库: jQuery.validate、jQuery.form、jQuery.blockUI、json2
为单页面应用程序(AngularJs、Durandaljs)和多页面应用程序(Bootstrap+Jquery)提供了项目模板。
自动创建Javascript 的代理层来更方便使用Web Api
封装一些Javascript 函数,更方便地使用ajax、消息框、通知组件、忙状态的遮罩层等等
3、zero模块
身份验证与授权管理(通过ASP.NET Identity实现的)
用户&角色管理
系统设置存取管理(系统级、租户级、用户级,作用范围自动管理)
审计日志(自动记录每一次接口的调用者和参数)
以上摘自阳铭系列教程
三、从ABP官网获取模版
ABP模版地址:http://www.aspnetboilerplate.com/Templates
1、选择选择MPA,因为AngularJs或DurandalJs不太懂;
2、选择ORM框架(Entity Framework或NHibernate)我选择EF;
3、zero模块先不要选择
4、起个名字,我起的FirstABP
点击“CREATE MY PROJECT”下载一个zip压缩文件,用vs2013打开如下结构:
打开每个项目里引用了Abp组件和其他第三方组件,需要Nuget重新引用下,
生成下看看还有没有错误,然后把FirstABP.Web设为起始项目,F5
四、简单Demo
1、在FirstABP.Core 新建People文件夹,然后建一个Person实体

using Abp.Domain.Entities; namespace FirstABP.People
{
public class Person : Entity
{
public virtual string Name { get; set; } public virtual int? Age { get; set; }
}
}

实体继承Abp.Domain.Entities.Entity基类,默认会有一个int类型自增的Id,如果想用其他类型可以指定,例如Abp.Domain.Entities.Entity<string>
2、把新建的Person实体类加入添加到IDbSet
在FirstABP.EntityFramework类库EntityFramework文件夹下的FirstABPDbContext文件里面

using System.Data.Entity;
using Abp.EntityFramework;
using FirstABP.People; namespace FirstABP.EntityFramework
{
public class FirstABPDbContext : AbpDbContext
{
//TODO: Define an IDbSet for each Entity...
public virtual IDbSet<Person> Person { get; set; }
//Example:
//public virtual IDbSet<User> Users { get; set; } /* NOTE:
* Setting "Default" to base class helps us when working migration commands on Package Manager Console.
* But it may cause problems when working Migrate.exe of EF. If you will apply migrations on command line, do not
* pass connection string name to base classes. ABP works either way.
*/
public FirstABPDbContext()
: base("Default")
{ } /* NOTE:
* This constructor is used by ABP to pass connection string defined in FirstABPDataModule.PreInitialize.
* Notice that, actually you will not directly create an instance of FirstABPDbContext since ABP automatically handles it.
*/
public FirstABPDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{ }
}
}

3、Database Migrations创建库和表
FirstABP.Web的webconfig,自动创建FirstABP数据库
<connectionStrings>
<add name="Default" connectionString="Server=localhost; Database=FirstABP; Trusted_Connection=True;" providerName="System.Data.SqlClient"/>
</connectionStrings>
修改SimpleTaskSystem.EntityFramework项目下Migrations文件夹下的Configuration.cs文件

using System.Data.Entity.Migrations;
using FirstABP.People; namespace FirstABP.Migrations
{
internal sealed class Configuration : DbMigrationsConfiguration<FirstABP.EntityFramework.FirstABPDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
ContextKey = "FirstABP";
} protected override void Seed(FirstABP.EntityFramework.FirstABPDbContext context)
{
// This method will be called every time after migrating to the latest version.
// You can add any seed data here... context.Person.AddOrUpdate(p => p.Name,
new Person { Name = "Joye.NET",Age=25 },
new Person { Name = "Jerry.Core",Age=25 },
new Person { Name = "longhao",Age=25 },
new Person { Name = "xmm",Age=25 });
}
}
}

通过 工具 -> Nuget程序包管理器 - > 程序包管理器控制台, 默认项目需要选中FirstABP.EntityFramework,Add-Migration “InitialCreate” 创建
Migrations文件夹下生成一个201605170608193_InitialCreate.cs文件

namespace FirstABP.Migrations
{
using System;
using System.Data.Entity.Migrations; public partial class InitialCreate : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.People",
c => new
{
Id = c.Int(nullable: false, identity: true),
Name = c.String(),
Age = c.Int(),
})
.PrimaryKey(t => t.Id); } public override void Down()
{
DropTable("dbo.People");
}
}
}

继续执行“Update-Database”,会自动在数据库创建相应的数据表:
如果出现下图的问题,可能是Nuget版本太低,需要升级下,
4、定义仓储接口
FirstABP.Core类库的people下新建IPersonRepository.cs

using System;
using System.Collections.Generic;
using Abp.Domain.Repositories; namespace FirstABP.People
{
public interface IPersonRepository : IRepository<Person,Int32>
{
List<Person> GetPersons();
}
}

5、实现仓储接口
FirstABP.EntityFramework类库EntityFramework下的Repositories文件建PersonRepository.cs文件

using System;
using System.Collections.Generic;
using System.Linq;
using Abp.EntityFramework;
using FirstABP.People; namespace FirstABP.EntityFramework.Repositories
{
public class PersonRepository : FirstABPRepositoryBase<Person,Int32>,IPersonRepository
{
public PersonRepository(IDbContextProvider<FirstABPDbContext> dbContextProvider) : base(dbContextProvider)
{
} public List<Person> GetPersons()
{
//在仓储方法中,不用处理数据库连接、DbContext和数据事务,ABP框架会自动处理。
//GetAll() 返回一个 IQueryable<T>接口类型
var query = GetAll();
return query.OrderByDescending(p=>p.Id).ToList();
}
}
}

6、创建领域服务(FirstABP.Application)
接口

using Abp.Application.Services;
using FirstABP.People.DTO; namespace FirstABP.People
{
public interface IPersonService : IApplicationService
{
GetAllPeopleOutput GetPersons();
}
}

实现:

using System.Collections.Generic;
using Abp.Application.Services;
using AutoMapper;
using FirstABP.People.DTO; namespace FirstABP.People
{
public class PersonService : ApplicationService, IPersonService
{
private readonly IPersonRepository _personRepository; /// <summary>
/// 构造函数自动注入
/// </summary>
/// <param name="personRepository"></param>
public PersonService(IPersonRepository personRepository)
{
_personRepository = personRepository;
} public GetAllPeopleOutput GetPersons()
{
var persons = _personRepository.GetPersons();
//用AutoMapper自动将List<Peopson>转换成List<PeopsonDto>
return new GetAllPeopleOutput
{
People = Mapper.Map<List<PersonDto>>(persons)
};
}
}
}

7、在web获取调用
代码:

using System.Web.Mvc;
using FirstABP.People; namespace FirstABP.Web.Controllers
{
public class HomeController : FirstABPControllerBase
{
private readonly IPersonService _personService; public HomeController(IPersonService personService)
{
_personService = personService;
} public ActionResult Index()
{
//获取列表
var p = _personService.GetPersons(); return View("~/App/Main/views/layout/layout.cshtml"); //Layout of the angular application.
}
}
}

运行结果:
最后看看新增了那些代码:
代码下载:https://yunpan.cn/cSwC9CbNtDMFt 访问密码 788c
深入学习推荐到
DDD的ABP开发框架的更多相关文章
- 线上分享-- 基于DDD的.NET开发框架-ABP介绍
前言 为了能够帮助.Net开发者开拓视野,更好的把最新的技术应用到工作中,我在3月底受邀到如鹏网.net训练营直播间为各位学弟学妹们进行ABP框架的直播分享.同时为了让更多的.NET开发者了解ABP框 ...
- DDD的.NET开发框架
基于DDD的.NET开发框架ABP实例,多租户 (Sass)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍 介绍 基于ABPZERO的多租户 (Sass) ...
- ABP开发框架前后端开发系列---(14)基于Winform的ABP快速开发框架
前面介绍了很多ABP系列的文章,一步一步的把我们日常开发中涉及到的Web API服务构建.登录日志和操作审计日志.字典管理模块.省份城市的信息维护.权限管理模块中的组织机构.用户.角色.权限.菜单等内 ...
- ABP开发框架前后端开发系列---(3)框架的分层和文件组织
在前面随笔<ABP开发框架前后端开发系列---(2)框架的初步介绍>中,我介绍了ABP应用框架的项目组织情况,以及项目中领域层各个类代码组织,以便基于数据库应用的简化处理.本篇随笔进一步对 ...
- ABP开发框架前后端开发系列---(2)框架的初步介绍
在前面随笔<ABP开发框架前后端开发系列---(1)框架的总体介绍>大概介绍了这个ABP框架的主要特点,以及介绍了我对这框架的Web API应用优先的一些看法,本篇继续探讨ABP框架的初步 ...
- ABP开发框架前后端开发系列---(10)Web API调用类的简化处理
在较早期的随笔<ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用>已经介绍了Web API调用类的封装处理,虽然这些调用类我们可以使用代码生成工具快 ...
- ABP开发框架前后端开发系列---(5)Web API调用类在Winform项目中的使用
在前面几篇随笔介绍了我对ABP框架的改造,包括对ABP总体的介绍,以及对各个业务分层的简化,Web API 客户端封装层的设计,使得我们基于ABP框架的整体方案越来越清晰化, 也越来越接近实际的项目开 ...
- ABP开发框架前后端开发系列---(4)Web API调用类的封装和使用
在前面随笔介绍ABP应用框架的项目组织情况,以及项目中领域层各个类代码组织,以及简化了ABP框架的各个层的内容,使得我们项目结构更加清晰.上篇随笔已经介绍了字典模块中应用服务层接口的实现情况,并且通过 ...
- ABP开发框架前后端开发系列---(11)菜单的动态管理
在前面随笔<ABP开发框架前后端开发系列---(9)ABP框架的权限控制管理>中介绍了基于ABP框架服务构建的Winform客户端,客户端通过Web API调用的方式进行获取数据,从而实现 ...
随机推荐
- C语言学习_include<>与include""的区别
经常会遇到两种include引用头文件的情况,其实区别很简单,如下: 一.#include< > #include< > 引用的是编译器的类库路径里面的头文件. 假如你编译器定 ...
- uva11549 Floyd判圈法
题意: 给两个数n, k,每次将k平方取k的前n位,问所有出现过的数的最大值 原来这就是floyd判圈法.. #include<cstdio> #include<cstdlib> ...
- 【设计模式 - 2】之单例模式(Singleton)
1 模式简介 单例模式在代码中是非常常用的,如线程池.数据库连接.注册表.共享资源.一些非常消耗资源的组件,等等. 单例模式主要解决如下问题: 确保一个特殊类的实例是独一无二的: 确保这个类 ...
- smarty、thinkphp中的html加载其他的html文件的方式
1.smarty 在模板文件中,使用定界符 {include file="header.html"} 不可以省略.html 2.thinkphp的html文件中 <incl ...
- 算法----希尔排序(shell sort)
在分析插入排序(插入排序算法实现)的算法性能的过程时知道.当数组规模较小或者存在较多的有序子序列时.插入排序将会在非常短的时间内完毕数组的排序,为此能够设计一个单调序列h[n],将数组分为多个小的序列 ...
- Qt之遍历文件夹(经典详解)
关于Qt操作文件夹.文件的知识用途较多,比如遍历下一层乃至所有子孙文件.文件夹,获取它们的一些信息(大小.类型.最后更改时间等).当然,也可以进行级联删除. 首先看简单的: 一.Qt遍历文件夹 ...
- android 06 LinearLayout
xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:la ...
- Execution Contexts (执行上下文)
本章我们一起讨论一下ECMAScript的执行上下文及相关可执行代码的各种类型.so...什么是执行上下文?我们来看看定义: 每次当控制器转到ECMAScript可执行代码的时候, 即会进入到一个执行 ...
- IOS的工程目录结构和生命周期
IOS的工程目录结构和生命周期 ·simple table文件夹:工程相关源代码和配置文件 BIDAppDelegate : 委托的声明和实现 BIDViewController: 视图控 ...
- android开发之调试技巧 分类: android 学习笔记 2015-07-18 21:30 140人阅读 评论(0) 收藏
我们都知道,android的调试打了断点之后运行时要使用debug as->android application 但是这样的运行效率非常低,那么我们有没有快速的方法呢? 当然有. 我们打完断点 ...