婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 基于ASP.NET MVC的ABP框架入門學習教程

基于ASP.NET MVC的ABP框架入門學習教程

熱門標簽:網絡電話外呼系統上海 外呼電話機器人成本 400電話辦理怎么樣 地圖標注軟件免費下載 西寧呼叫中心外呼系統線路商 聯通官網400電話辦理 臨沂智能電話機器人加盟 百應電話機器人外呼系統 蘇州如何辦理400電話

為什么使用ABP
我們近幾年陸續開發了一些Web應用和桌面應用,需求或簡單或復雜,實現或優雅或丑陋。一個基本的事實是:我們只是積累了一些經驗或提高了對,NET的熟悉程度。
隨著軟件開發經驗的不斷增加,我們發現其實很多工作都是重復機械的,而且隨著軟件復雜度的不斷提升,以往依靠經驗來完成一些簡單的增刪改查的做法已經行不通了。特別是用戶的要求越來越高,希望添加的功能越來多,目前這種開發模式,已經捉襟見肘。我很難想象如何在現有的模式下進行多系統的持續集成并添加一些新的特性。
開發一個系統時,我們不可避免的會使用各種框架。數據持久層實現、日志、ASP.NET MVC、IOC以及自動映射等。一個高質量的軟件系統往往還有全局容錯,消息隊列等組件。
把上述這些組件組合到一起的時候,其復雜度會急劇上升。一般個人和小團隊的技術水平,很難設計出一個均衡協調的框架。對于傳統的所謂三層架構,我也是很持懷疑態度的。(月薪15k的程序員搞的三層架構,我也仔細讀過,也是問題多多,并不能解釋為什么要使用三層)。
其實,我們無非是希望在編程的時候,把大部分的注意力全部集中到業務實現上。不要過多的考慮基礎的軟件結構上的種種問題。應該有一個框框或者一種范式來提供基本的服務,如日志、容錯和AOP,DI等。
稍微正規一點的公司經過多年沉淀都形成了自己的內部軟件框架,他們在開發軟件的時候并不是從一片空白開始的。而是從一個非常牢固的基礎平臺上開始構建的。這樣大大提高了開發速度,而且一種架構往往也決定了分工協作的模式。我們目前之所以無法分工協作,根本原因也是缺少一套成熟穩定的基礎開發架構和工作流程。
目前.NET上有不少開源框架。比如Apworks和ABP。其中Apworks是中國人寫的一套開源框架。它是一個全功能的,不僅可以寫分布式應用,也可以寫桌面應用。ABP的全稱是Asp.net boilerplate project(asp.net樣板工程)。是github上非常活躍的一個開源項目。它并沒有使用任何新的技術,只是由兩名架構師將asp.net開發中常用的一些工具整合到了一起,并且部分實現了DDD的概念。是一個開箱即用的框架,可以作為asp.net分布式應用的一個良好起點。
使用框架當然有代價,你必須受到框架強API的侵入,抑或要使用他的方言。而且這個框架想要吃透,也要付出很大的學習成本。但是好處也是顯而易見的。業界頂尖的架構師已經為你搭建好了一套基礎架構,很好的回應了關于一個軟件系統應該如何設計,如何規劃的問題,并且提供了一套最佳實踐和范例。
學習雖然要付出成本,但是經過漫長的跋涉,我們從一無所知已經站到了工業級開發的門檻上。基于這個框架,我們可以很好的來劃分任務,進行單元測試等。大大降低了軟件出現BUG的幾率。

從模板創建空的web應用程序

ABP的官方網站:http://www.aspnetboilerplate.com
ABP在Github上的開源項目:https://github.com/aspnetboilerplate
ABP提供了一個啟動模板用于新建的項目(盡管你能手動地創建項目并且從nuget獲得ABP包,模板的方式更容易)。
轉到www.aspnetboilerplate.com/Templates從模板創建你的應用程序。
你可以選擇SPA(AngularJs或DurandalJs)或者選擇MPA(經典的多頁面應用程序)項目。可以選擇Entity Framework或NHibernate作為ORM框架。
這里我們選擇AngularJs和Entity Framework,填入項目名稱“SimpleTaskSystem”,點擊“CREATE MY PROJECT”按鈕可以下載一個zip壓縮包,解壓后得到VS2013的解決方案,使用的.NET版本是 4.5.1。

每個項目里引用了Abp組件和其他第三方組件,需要從Nuget下載。

黃色感嘆號圖標,表示這個組件在本地文件夾中不存在,需要從Nuget上還原。操作如下:

要讓項目運行起來,還得創建一個數據庫。這個模板假設你正在使用SQL2008或者更新的版本。當然也可以很方便地換成其他的關系型數據庫。
打開Web.Config文件可以查看和配置鏈接字符串:

復制代碼 代碼如下:

add name="Default" connectionString="Server=localhost; Database=SimpleTaskSystemDb; Trusted_Connection=True;" />

(在后面用到EF的Code first數據遷移時,會自動在SQL Server數據庫中創建一個名為SimpleTaskSystemDb的數據庫。)
就這樣,項目已經準備好運行了!打開VS2013并且按F5:
下面將逐步實現這個簡單的任務系統程序

創建實體
把實體類寫在Core項目中,因為實體是領域層的一部分。
一個簡單的應用場景:創建一些任務(tasks)并分配給人。 我們需要Task和Person這兩個實體。
Task實體有幾個屬性:描述(Description)、創建時間(CreationTime)、任務狀態(State),還有可選的導航屬性(AssignedPerson)來引用Person。

public class Task : Entitylong>
{
  [ForeignKey("AssignedPersonId")]
  public virtual Person AssignedPerson { get; set; }

  public virtual int? AssignedPersonId { get; set; }

  public virtual string Description { get; set; }

  public virtual DateTime CreationTime { get; set; }

  public virtual TaskState State { get; set; }

  public Task()
  {
    CreationTime = DateTime.Now;
    State = TaskState.Active;
  }
}


Person實體更簡單,只定義了一個Name屬性:
public class Person : Entity
{
  public virtual string Name { get; set; }
}

在ABP框架中,有一個Entity基類,它有一個Id屬性。因為Task類繼承自Entitylong>,所以它有一個long類型的Id。Person類有一個int類型的Id,因為int類型是Entity基類Id的默認類型,沒有特別指定類型時,實體的Id就是int類型。

創建DbContext
使用EntityFramework需要先定義DbContext類,ABP的模板已經創建了DbContext文件,我們只需要把Task和Person類添加到IDbSet,請看代碼:

public class SimpleTaskSystemDbContext : AbpDbContext
{
  public virtual IDbSetTask> Tasks { get; set; }

  public virtual IDbSetPerson> People { get; set; }

  public SimpleTaskSystemDbContext()
    : base("Default")
  {

  }

  public SimpleTaskSystemDbContext(string nameOrConnectionString)
    : base(nameOrConnectionString)
  {
      
  }
}

通過Database Migrations創建數據庫表
我們使用EntityFramework的Code First模式創建數據庫架構。ABP模板生成的項目已經默認開啟了數據遷移功能,我們修改SimpleTaskSystem.EntityFramework項目下Migrations文件夾下的Configuration.cs文件:

internal sealed class Configuration :

DbMigrationsConfigurationSimpleTaskSystem.EntityFramework.SimpleTaskSystemDbContext>
{
  public Configuration()
  {
    AutomaticMigrationsEnabled = false;
  }

  protected override void Seed(SimpleTaskSystem.EntityFramework.SimpleTaskSystemDbContext context)
  {
    context.People.AddOrUpdate(
      p => p.Name,
      new Person {Name = "Isaac Asimov"},
      new Person {Name = "Thomas More"},
      new Person {Name = "George Orwell"},
      new Person {Name = "Douglas Adams"}
      );
  }
}

在VS2013底部的“程序包管理器控制臺”窗口中,選擇默認項目并執行命令“Add-Migration InitialCreate”

會在Migrations文件夾下生成一個xxxx-InitialCreate.cs文件,內容如下:

public partial class InitialCreate : DbMigration
{
  public override void Up()
  {
    CreateTable(
      "dbo.StsPeople",
      c => new
        {
          Id = c.Int(nullable: false, identity: true),
          Name = c.String(),
        })
      .PrimaryKey(t => t.Id);
      
    CreateTable(
      "dbo.StsTasks",
      c => new
        {
          Id = c.Long(nullable: false, identity: true),
          AssignedPersonId = c.Int(),
          Description = c.String(),
          CreationTime = c.DateTime(nullable: false),
          State = c.Byte(nullable: false),
        })
      .PrimaryKey(t => t.Id)
      .ForeignKey("dbo.StsPeople", t => t.AssignedPersonId)
      .Index(t => t.AssignedPersonId);      
  }
    
  public override void Down()
  {
    DropForeignKey("dbo.StsTasks", "AssignedPersonId", "dbo.StsPeople");
    DropIndex("dbo.StsTasks", new[] { "AssignedPersonId" });
    DropTable("dbo.StsTasks");
    DropTable("dbo.StsPeople");
  }
}

然后繼續在“程序包管理器控制臺”執行“Update-Database”,會自動在數據庫創建相應的數據表:
PM> Update-Database

數據庫顯示如下:

(以后修改了實體,可以再次執行Add-Migration和Update-Database,就能很輕松的讓數據庫結構與實體類的同步)

定義倉儲接口
通過倉儲模式,可以更好把業務代碼與數據庫操作代碼更好的分離,可以針對不同的數據庫有不同的實現類,而業務代碼不需要修改。
定義倉儲接口的代碼寫到Core項目中,因為倉儲接口是領域層的一部分。
我們先定義Task的倉儲接口:

public interface ITaskRepository : IRepositoryTask, long>
{
  ListTask> GetAllWithPeople(int? assignedPersonId, TaskState? state);
}

它繼承自ABP框架中的IRepository泛型接口。
在IRepository中已經定義了常用的增刪改查方法:

所以ITaskRepository默認就有了上面那些方法。可以再加上它獨有的方法GetAllWithPeople(...)。

不需要為Person類創建一個倉儲類,因為默認的方法已經夠用了。ABP提供了一種注入通用倉儲的方式,將在后面“創建應用服務”一節的TaskAppService類中看到。

實現倉儲類
我們將在EntityFramework項目中實現上面定義的ITaskRepository倉儲接口。

通過模板建立的項目已經定義了一個倉儲基類:SimpleTaskSystemRepositoryBase(這是一種比較好的實踐,因為以后可以在這個基類中添加通用的方法)。

public class TaskRepository : SimpleTaskSystemRepositoryBaseTask, long>, ITaskRepository
{
  public ListTask> GetAllWithPeople(int? assignedPersonId, TaskState? state)
  {
    //在倉儲方法中,不用處理數據庫連接、DbContext和數據事務,ABP框架會自動處理。
      
    var query = GetAll(); //GetAll() 返回一個 IQueryableT>接口類型
      
    //添加一些Where條件

    if (assignedPersonId.HasValue)
    {
      query = query.Where(task => task.AssignedPerson.Id == assignedPersonId.Value);
    }

    if (state.HasValue)
    {
      query = query.Where(task => task.State == state);
    }

    return query
      .OrderByDescending(task => task.CreationTime)
      .Include(task => task.AssignedPerson)
      .ToList();
  }
}

TaskRepository繼承自SimpleTaskSystemRepositoryBase并且實現了上面定義的ITaskRepository接口。

 
創建應用服務(Application Services)
在Application項目中定義應用服務。首先定義Task的應用服務層的接口:

public interface ITaskAppService : IApplicationService
{
  GetTasksOutput GetTasks(GetTasksInput input);
  void UpdateTask(UpdateTaskInput input);
  void CreateTask(CreateTaskInput input);
}

ITaskAppService繼承自IApplicationService,ABP自動為這個類提供一些功能特性(比如依賴注入和參數有效性驗證)。

然后,我們寫TaskAppService類來實現ITaskAppService接口:

public class TaskAppService : ApplicationService, ITaskAppService
{
  private readonly ITaskRepository _taskRepository;
  private readonly IRepositoryPerson> _personRepository;
    
  /// summary>
  /// 構造函數自動注入我們所需要的類或接口
  /// /summary>
  public TaskAppService(ITaskRepository taskRepository, IRepositoryPerson> personRepository)
  {
    _taskRepository = taskRepository;
    _personRepository = personRepository;
  }
    
  public GetTasksOutput GetTasks(GetTasksInput input)
  {
    //調用Task倉儲的特定方法GetAllWithPeople
    var tasks = _taskRepository.GetAllWithPeople(input.AssignedPersonId, input.State);

    //用AutoMapper自動將ListTask>轉換成ListTaskDto>
    return new GetTasksOutput
        {
          Tasks = Mapper.MapListTaskDto>>(tasks)
        };
  }
    
  public void UpdateTask(UpdateTaskInput input)
  {
    //可以直接Logger,它在ApplicationService基類中定義的
    Logger.Info("Updating a task for input: " + input);

    //通過倉儲基類的通用方法Get,獲取指定Id的Task實體對象
    var task = _taskRepository.Get(input.TaskId);

    //修改task實體的屬性值
    if (input.State.HasValue)
    {
      task.State = input.State.Value;
    }

    if (input.AssignedPersonId.HasValue)
    {
      task.AssignedPerson = _personRepository.Load(input.AssignedPersonId.Value);
    }

    //我們都不需要調用Update方法
    //因為應用服務層的方法默認開啟了工作單元模式(Unit of Work)
    //ABP框架會工作單元完成時自動保存對實體的所有更改,除非有異常拋出。有異常時會自動回滾,因為工作單元默認開啟數據庫事務。
  }

  public void CreateTask(CreateTaskInput input)
  {
    Logger.Info("Creating a task for input: " + input);

    //通過輸入參數,創建一個新的Task實體
    var task = new Task { Description = input.Description };

    if (input.AssignedPersonId.HasValue)
    {
      task.AssignedPersonId = input.AssignedPersonId.Value;
    }

    //調用倉儲基類的Insert方法把實體保存到數據庫中
    _taskRepository.Insert(task);
  }
}

TaskAppService使用倉儲進行數據庫操作,它通往構造函數注入倉儲對象的引用。

數據驗證

如果應用服務(Application Service)方法的參數對象實現了IInputDto或IValidate接口,ABP會自動進行參數有效性驗證。

CreateTask方法有一個CreateTaskInput參數,定義如下:

public class CreateTaskInput : IInputDto
{
  public int? AssignedPersonId { get; set; }

  [Required]
  public string Description { get; set; }
}

Description屬性通過注解指定它是必填項。也可以使用其他 Data Annotation 特性。

如果你想使用自定義驗證,你可以實現ICustomValidate 接口:

public class UpdateTaskInput : IInputDto, ICustomValidate
{
  [Range(1, long.MaxValue)]
  public long TaskId { get; set; }

  public int? AssignedPersonId { get; set; }

  public TaskState? State { get; set; }

  public void AddValidationErrors(ListValidationResult> results)
  {
    if (AssignedPersonId == null  State == null)
    {
      results.Add(new ValidationResult("AssignedPersonId和State不能同時為空!", new[] { "AssignedPersonId", "State" }));
    }
  }
}

你可以在AddValidationErrors方法中寫自定義驗證的代碼。

創建Web Api服務
ABP可以非常輕松地把Application Service的public方法發布成Web Api接口,可以供客戶端通過ajax調用。

DynamicApiControllerBuilder
  .ForAllIApplicationService>(Assembly.GetAssembly(typeof (SimpleTaskSystemApplicationModule)), "tasksystem")
  .Build();

SimpleTaskSystemApplicationModule這個程序集中所有繼承了IApplicationService接口的類,都會自動創建相應的ApiController,其中的公開方法,就會轉換成WebApi接口方法。

可以通過http://xxx/api/services/tasksystem/Task/GetTasks這樣的路由地址進行調用。

通過上面的案例,大致介紹了領域層、基礎設施層、應用服務層的用法。

現在,可以在ASP.NET MVC的Controller的Action方法中直接調用Application Service的方法了。

如果用SPA單頁編程,可以直接在客戶端通過ajax調用相應的Application Service的方法了(通過創建了動態Web Api)。

您可能感興趣的文章:
  • BootStrap table表格插件自適應固定表頭(超好用)
  • 值得分享的輕量級Bootstrap Table表格插件
  • ABP入門系列應用BootstrapTable表格插件

標簽:海西 聊城 平涼 甘肅 清遠 中衛 慶陽 臨夏

巨人網絡通訊聲明:本文標題《基于ASP.NET MVC的ABP框架入門學習教程》,本文關鍵詞  基于,ASP.NET,MVC,的,ABP,框架,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《基于ASP.NET MVC的ABP框架入門學習教程》相關的同類信息!
  • 本頁收集關于基于ASP.NET MVC的ABP框架入門學習教程的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    日韩欧美综合在线| 亚洲综合丝袜美腿| 久久噜噜亚洲综合| 亚洲一二三区不卡| 极品少妇xxxx精品少妇| 欧美美女直播网站| 亚洲一区二区三区在线| 国产成人在线视频网址| 久久色.com| 美女视频黄频大全不卡视频在线播放| 波多野结衣91| 日韩理论在线观看| 一本大道久久a久久精品综合| 国产人久久人人人人爽| 国产九九视频一区二区三区| 久久先锋影音av鲁色资源网| 九一九一国产精品| 日本一区二区三区dvd视频在线| 国产九色精品成人porny| 国产蜜臀97一区二区三区| 99麻豆久久久国产精品免费| 亚洲精品中文字幕乱码三区 | 欧美大片一区二区| 久久成人久久鬼色| 国产视频一区在线播放| 粉嫩aⅴ一区二区三区四区| 欧美videos大乳护士334| 狠狠色狠狠色综合日日91app| 久久久久综合网| 日韩和的一区二区| 亚洲乱码国产乱码精品精小说| 亚洲激情网站免费观看| 久久久亚洲精品石原莉奈| 一区二区三区精品| 国产乱码精品一区二区三| 色婷婷亚洲婷婷| 欧美经典一区二区| 裸体一区二区三区| 日韩欧美中文字幕制服| 亚洲精选一二三| 国产一区二区三区黄视频 | 91精品国产综合久久福利| 国产精品视频观看| 亚洲午夜国产一区99re久久| 欧美男同性恋视频网站| 偷拍自拍另类欧美| 亚洲日本在线观看| 欧美精品乱码久久久久久按摩| 亚洲国产综合色| 中文字幕免费不卡| 在线精品视频一区二区| 日韩免费看网站| 中文一区二区在线观看| 久久国产尿小便嘘嘘| 91小视频在线免费看| 久久九九久久九九| 亚洲最大色网站| av激情亚洲男人天堂| 国内精品国产三级国产a久久| 六月丁香婷婷色狠狠久久| 国产精品88888| 日韩一区二区麻豆国产| 精品少妇一区二区三区免费观看| 欧美成人免费网站| 麻豆高清免费国产一区| 97aⅴ精品视频一二三区| 欧美日本乱大交xxxxx| 精品国产在天天线2019| 亚洲欧美一区二区三区孕妇| 亚洲一区二区三区自拍| 狠狠色丁香久久婷婷综合_中| 成人av中文字幕| 日本不卡123| 99精品视频一区| 91亚洲精品久久久蜜桃网站| 欧美一级二级三级乱码| 久久精品人人做人人综合| 亚洲精选视频在线| 99久久精品国产导航| 麻豆精品视频在线观看免费| 亚洲欧美成aⅴ人在线观看| 91精品国产欧美日韩| 99久久精品费精品国产一区二区| 五月激情综合网| 男人的天堂亚洲一区| 亚洲欧美日韩一区二区 | 99久久婷婷国产综合精品| 国产精品香蕉一区二区三区| 国产美女av一区二区三区| 国产一区二区精品久久| 日韩在线一区二区| 欧美国产精品一区二区| 久久久久久久久久久电影| 国产乱淫av一区二区三区| 蜜桃av噜噜一区| 日韩精品电影一区亚洲| 无吗不卡中文字幕| 亚洲成人三级小说| 精品一区二区三区在线播放| 日韩电影在线看| 国产乱人伦精品一区二区在线观看| 日韩国产一二三区| 粉嫩嫩av羞羞动漫久久久 | 欧美午夜一区二区三区| 欧美精品乱码久久久久久| 欧美日韩成人综合在线一区二区| 欧美精品一区二区三区在线| 久久噜噜亚洲综合| 亚洲伊人伊色伊影伊综合网| 亚洲精品视频在线观看免费| 免费看日韩a级影片| 秋霞午夜av一区二区三区| 东方欧美亚洲色图在线| va亚洲va日韩不卡在线观看| 欧美体内she精高潮| 91精品国产欧美日韩| 久久久国产精品不卡| 国产精品久久久久久久久久久免费看| 亚洲综合区在线| 亚洲国产日韩a在线播放性色| 国产精品综合一区二区| 日韩精彩视频在线观看| 国产不卡视频一区二区三区| 色哟哟国产精品免费观看| 91丨九色丨蝌蚪丨老版| 最新高清无码专区| 免费成人美女在线观看.| 久久久亚洲综合| 风间由美一区二区三区在线观看| 成人av在线播放网站| 不卡视频在线观看| 91麻豆swag| youjizz久久| 亚洲国产精品精华液ab| 免费观看一级特黄欧美大片| 久久久天堂av| 高清国产一区二区| 久久久久久久久久久久久女国产乱| 日韩欧美成人午夜| 成人高清视频免费观看| 亚洲精品一线二线三线无人区| 欧美日韩不卡一区二区| 亚洲精品成人在线| 欧美色国产精品| 国产91精品欧美| 中文字幕人成不卡一区| 成人午夜视频网站| 亚洲免费观看在线观看| 国产成人av电影| 亚洲欧洲av一区二区三区久久| 一本色道久久综合精品竹菊| 国内外成人在线视频| 91精品久久久久久久久99蜜臂| 日韩一区二区影院| 久久激情综合网| 日韩欧美激情四射| 一区二区三区电影在线播| 亚洲小少妇裸体bbw| 国产裸体歌舞团一区二区| 91美女在线视频| 一区二区三区四区视频精品免费 | 色伊人久久综合中文字幕| 成人免费视频在线观看| 日韩免费成人网| 中文字幕一区二区三区四区| 日本午夜精品视频在线观看| 欧美三级日韩在线| 一区二区欧美精品| 色一区在线观看| 日韩av二区在线播放| 欧美视频在线不卡| 日韩精品一二区| 激情久久五月天| 国产精品久久久久久久第一福利| 偷窥国产亚洲免费视频| 欧美一区二区三区在| 一区二区三区高清在线| 日韩欧美中文一区| 天堂蜜桃91精品| 国产欧美日韩在线| 国产美女视频91| 成人在线一区二区三区| 亚洲三级在线看| 欧美色电影在线| 午夜精品久久一牛影视| 亚洲一卡二卡三卡四卡无卡久久| 麻豆高清免费国产一区| 成人av网站在线观看免费| 日韩一区中文字幕| 污片在线观看一区二区| 国产乱码精品一品二品| 国产精品一区二区免费不卡| 日本伦理一区二区| 国产亚洲欧美日韩日本| 亚洲精品网站在线观看| 亚洲精品免费在线观看| 国产精品久久久久一区二区三区| 精品国产露脸精彩对白| 亚洲chinese男男1069| 国产色产综合产在线视频|