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

    返回ABP系列

    ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。

    ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。

    ABP的官方网站:http://www.aspnetboilerplate.com

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

    Github上的开源项目:https://github.com/aspnetboilerplate

    一、基本概念

    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、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

    深入学习推荐到

    阳铭系列教程:http://www.cnblogs.com/mienreal/p/4528470.html

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

  • 相关阅读:
    设计模式之四(抽象工厂模式第二回合)
    C# try catch finally
    设计模式之三(工厂方法模式)
    C# XML与Json之间的相互转换
    Google免费的SVN服务器管理VS2010代码
    设计模式之四(抽象工厂模式第一回合)
    MVC项目开发中那些用到的知识点(Jquery ajax提交Json后台处理)
    设计模式之四(抽象工厂模式第三回合)
    设计模式之二(简单工厂模式)
    Jquery的$命名冲突
  • 原文地址:https://www.cnblogs.com/yinrq/p/5502294.html
Copyright © 2011-2022 走看看