700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > abp angular 和mvc_[译]ABP框架使用AngularJs ASP.NET MVC Web API和EntityFram

abp angular 和mvc_[译]ABP框架使用AngularJs ASP.NET MVC Web API和EntityFram

时间:2019-07-19 10:43:18

相关推荐

abp angular 和mvc_[译]ABP框架使用AngularJs ASP.NET MVC Web API和EntityFram

本文演示ABP框架如何使用AngularJs, MVC,Web API 和EntityFramework构建基于N层架构的多语言SPA应用程序

演示程序截图如上所示.

内容摘要

介绍

在这篇文章, 我将基于以下框架演示如何开发单页面的(SPA)应用程序:

MVC和 Web API–web站点的基础框架.

Angularjs–SPA 框架.

EntityFramework–ORM (Object-Relational Mapping)框架

Castle Windsor –依赖注入框架.

Twitter Bootstrap– 前端框架.

Log4Net来记录日志,AutoMapper实体对象映射.

和 Boilerplate作为应用程序模板框架.

Boilerplate[1] 是一个开源的应用程序框架,它包含了一些常用的组件让您能够快速简单的开发应用. 它集成一些常用的基础框架. 比如依赖注入,领域驱动设计 和分层架构. 本应用演示ABP如何实现验证,异常处理,本地化和响应式设计.

使用 boilerplate 模板创建程序

Boilerplate给我们提供了一个非常好的构建企业应用的模板,以便节约我们构建应用程序的时间。

在/Templates目录,我们可以使用模板创建应用。

这里我选择SPA(单页面程序)使用AngularJs,EntityFramework框架. 然后输入项目名称SimpleTaskSystem.来创建和下载应用模版.下载的模版解决方案包含5个项目.Core项目是领域 (业务) 层,Application项目是应用层,WebApi项目实现了 Web Api 控制器,Web项目是展示层,最后EntityFramework项目实现了EntityFramework框架.

Note: 如果您下载本文演示实例, 你会看到解决方案有7个项目. 我把NHibernate和Durandal都放到本演示中.如果你对NHibernate,Durandal不感兴趣的话,可以忽略它们.

创建实体对象

我将创建一个简单的应用程序来演示任务和分配任务的人. 所以我需要创建Task实体对象和Person实体对象.

Task实体对象简单的定义了一些描述:CreationTime和Task的状态. 它同样包含了Person(AssignedPerson)的关联引用:

publicclassTask:Entity{[ForeignKey("AssignedPersonId")]publicvirtual PersonAssignedPerson{get;set;}publicvirtual int?AssignedPersonId{get;set;}publicvirtual stringDescription{get;set;}publicvirtual DateTimeCreationTime{get;set;}publicvirtual TaskStateState{get;set;}publicTask(){CreationTime=DateTime.Now;State=TaskState.Active;}}

Person实体对象简单的定义下Name:

publicclassPerson:Entity{publicvirtual stringName{get;set;}}

Boilerplate 给Entity类定义了Id属性. 从Entity 类派生实体对象将继承Id属性. Task 类从Entity派生将包含long类型的ID. Person 类包含int类型的ID. 因为int是默认的主键类型, 这里我不需要特殊指定.

我在这个Core项目里添加实体对象因为实体对象是属于领域/业务层的.

创建 DbContext

众所周知, EntityFramework使用DbContext类工作. 我们首先得定义它. Boilerplate创建了一个DbContext模板给我们. 我们只需要添加IDbSets给 Task and Person. 完整的 DbContext 类如下:

publicclassSimpleTaskSystemDbContext:AbpDbContext{publicvirtual IDbSetTasks{get;set;}publicvirtual IDbSetPeople{get;set;}publicSimpleTaskSystemDbContext():base("Default"){}publicSimpleTaskSystemDbContext(stringnameOrConnectionString):base(nameOrConnectionString){}}

我们还需要在web.config添加默认的连接字符串. 如下:

创建数据库迁移

我们将使用EntityFramework的Code First模式来迁移和创建数据库. Boilerplate模板默认支持签约但需要我们添加如下的Configuration 类:

internalinternal sealedclassConfiguration:DbMigrationsConfiguration{publicConfiguration(){AutomaticMigrationsEnabled=false;}protectedoverridevoidSeed(SimpleTaskSystem.EntityFramework.SimpleTaskSystemDbContextcontext){context.People.AddOrUpdate(p =>p.Name,newPerson{Name="Isaac Asimov"},newPerson{Name="Thomas More"},newPerson{Name="George Orwell"},newPerson{Name="Douglas Adams"});}}

另一种方法, 是在初始化的是添加4个Person. 我将创建初始迁移.打开包管理控台程序并输入以下命令:

Add-Migration “InitialCreate”命令创建InitialCreate 类如下:

publicpartialclassInitialCreate:DbMigration{publicoverridevoidUp(){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);}publicoverridevoidDown(){DropForeignKey("dbo.StsTasks","AssignedPersonId","dbo.StsPeople");DropIndex("dbo.StsTasks",new[]{"AssignedPersonId"});DropTable("dbo.StsTasks");DropTable("dbo.StsPeople");}}

我们已经创建了数据库类, 但是还没创建那数据库. 下面来创建数据库,命令如下:

PM> Update-Database

这个命令帮我们创建好了数据库并填充了初始数据:

当我们修改实体类时, 我们可以通过 Add-Migration 命令很容易的创建迁移类。需要更新数据库的时候则可以通过 Update-Database 命令. 关于更多的数据库迁移, 可以查看entity framework的官方文档.

定义库

在领域驱动设计中, repositories 用于实现特定的代码. Boilerplate 使用IRepository 接口给每个实体自动的创建repository. IRepository 定义了常用的方法如 select, insert, update, delete 等,更多如下:

我们还可以根据我们的需要来扩展 repository . 如果需要单独的实现接口的话,首先需要继承 repositories 接口. Task repository 接口如下:

public interface ITaskRepository : IRepository

{

List GetAllWithPeople(int? assignedPersonId, TaskState? state);

}

这继承了 Boilerplate 的IRepository接口.ITaskRepository默认定义了这些方法. 我们也可以添加自己的方法GetAllWithPeople(…).

这里不需要再为Person创建 repository 了,因为默认的方法已经足够. Boilerplate 提供了通用的 repositories 而不需要创建 repository 类. 在’构建应用程序服务层’ 章节中的TaskAppService 类中将演示这些..

repository 接口被定义在Core项目中因为它们是属于领域/业务层的.

实现库

我们需要实现上述的 ITaskRepository 接口. 我们在EntityFramework项目实现repositories. 因此,领域层完全独立于EntityFramework.

当我们创建项目模板, Boilerplate 在项目中为repositories定义了一些基本类:SimpleTaskSystemRepositoryBase. 这是一个非常好的方式来添加基本类,因为我们可以为repositories稍后添加方法. 你可以看下面代码定义的这个类.定义TaskRepository从它派生:

publicclassTaskRepository:SimpleTaskSystemRepositoryBase,ITaskRepository{publicListGetAllWithPeople(int?assignedPersonId,TaskState?state){//In repository methods, we do not deal with create/dispose DB connections, DbContexes and transactions. ABP handles it.varquery =GetAll();//GetAll() returns IQueryable, so we can query over it.//var query = Context.Tasks.AsQueryable(); //Alternatively, we can directly use EF's DbContext object.//var query = Table.AsQueryable(); //Another alternative: We can directly use 'Table' property instead of 'Context.Tasks', they are identical.//Add some Where conditions...if(assignedPersonId.HasValue){query =query.Where(task =>task.AssignedPerson.Id==assignedPersonId.Value);}if(state.HasValue){query =query.Where(task =>task.State==state);}returnquery

.OrderByDescending(task =>task.CreationTime).Include(task =>task.AssignedPerson)//Include assigned person in a single query .ToList();}}

上述代码TaskRepository派生自SimpleTaskSystemRepositoryBase并实现了ITaskRepository.

构建应用程序服务层

应用程序服务层被用于分离表示层和领域层并提供一些界面的样式方法. 在Application组件中定义应用程序服务. 首先定义task 应用程序服务的接口:

publicinterface ITaskAppService:IApplicationService{GetTasksOutputGetTasks(GetTasksInputinput);voidUpdateTask(UpdateTaskInputinput);voidCreateTask(CreateTaskInputinput);}

ITaskAppService继承自IApplicationService. 因此 Boilerplate自动的提供了一些类的特性(像依赖注入和验证).现在我们来实现ITaskAppService:

publicclassTaskAppService:ApplicationService,ITaskAppService{//These members set in constructor using constructor injection.privatereadonlyITaskRepository_taskRepository;privatereadonlyIRepository_personRepository;/// ///In constructor, we can get needed classes/interfaces.///They are sent here by dependency injection system automatically./// publicTaskAppService(ITaskRepositorytaskRepository,IRepositorypersonRepository){_taskRepository =taskRepository;_personRepository =personRepository;}publicGetTasksOutputGetTasks(GetTasksInputinput){//Called specific GetAllWithPeople method of task repository.vartasks =_taskRepository.GetAllWithPeople(input.AssignedPersonId,input.State);//Used AutoMapper to automatically convert List to List.returnnewGetTasksOutput{Tasks=Mapper.Map>(tasks)};}publicvoidUpdateTask(UpdateTaskInputinput){//We can use Logger, it's defined in ApplicationService base class.Logger.Info("Updating a task for input: "+input);//Retrieving a task entity with given id using standard Get method of repositories.vartask =_taskRepository.Get(input.TaskId);//Updating changed properties of the retrieved task entity.if(input.State.HasValue){task.State=input.State.Value;}if(input.AssignedPersonId.HasValue){task.AssignedPerson=_personRepository.Load(input.AssignedPersonId.Value);}//We even do not call Update method of the repository.//Because an application service method is a 'unit of work' scope as default.//ABP automatically saves all changes when a 'unit of work' scope ends (without any exception). }publicvoidCreateTask(CreateTaskInputinput){//We can use Logger, it's defined in ApplicationService class. Logger.Info(

abp angular 和mvc_[译]ABP框架使用AngularJs MVC Web API和EntityFramework构建N层架构的SPA应用程序...

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。