zoukankan      html  css  js  c++  java
  • 基于DDD的.NET开发框架

    一、基本概念

    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

  • 相关阅读:
    PAT 1006 Sign In and Sign Out
    PAT 1004. Counting Leaves
    JavaEE开发环境安装
    NoSql数据库探讨
    maven的配置
    VMWARE 下使用 32位 Ubuntu Linux ,不能给它分配超过3.5G 内存?
    XCODE 4.3 WITH NO GCC?
    在苹果虚拟机上跑 ROR —— Ruby on Rails On Vmware OSX 10.7.3
    推荐一首让人疯狂的好歌《Pumped Up Kicks》。好吧,顺便测下博客园可以写点无关技术的帖子吗?
    RUBY元编程学习之”编写你的第一种领域专属语言“
  • 原文地址:https://www.cnblogs.com/BluceLee/p/6528716.html
Copyright © 2011-2022 走看看