基於DDD的.NET開發框架 - 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

ABP官方文檔:http://www.aspnetboilerplate.com/Pages/Documents

強烈建議從事.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、AngularJSjQuery、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

深入學習推薦到

陽銘系列教程:http://www.cnblogs.com/mienreal/p/4528470.html

tkb至簡系列教程:http://www.cnblogs.com/farb/p/ABPTheory.html