在Apworks数据服务中使用基于Entity Framework Core的仓储(Repository)实现

《在ASP.NET Core中使用Apworks快速开发数据服务》一文中,我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API,通过该文的介绍,你会看到,使用Apworks框架开发数据服务是何等简单快捷,提供的功能也非常多,比如对Hypermedia的支持,以及提供丰富的异常信息和调用栈信息。另外,Apworks数据服务可以支持各种类型的仓储(Repository)实现,在该文的案例中,我使用了MongoDB作为仓储的实现,这是为了快速方便地演示数据服务的搭建过程。如果你所使用的是关系型数据库,也没有关系(意思是不要紧,不是说数据没有关系。。。-_-!!!),基于Entity Framework Core的仓储实现能够满足你的需求。

需要注意的一个问题

在以前老版本的Apworks中,仓储的接口是支持饥饿加载的,也就是说,在延迟加载被启用的时候,仓储允许通过显式指定一系列的对象属性,当主对象被返回时,这些属性所指向的子对象也会同时返回。这样的设计在当时的场景下是合理的,因为是否需要加载某些属性是可以在程序中指定的,对于类似MongoDB的仓储实现,它没有延迟加载的概念,因此可以忽略这个参数。在Apworks数据服务中,由于仓储的操作会直接被DataServiceController调用,而相关的查询条件都是来自于RESTful API的,因此,很难在API的层面来确定某些聚合的对象属性是否需要饥饿加载(Eager Loading)。另一方面,禁用延迟加载又会产生性能问题,因此,在当前版本的实现中,我还没有考虑好用何种方式来解决这个问题。或许可以通过HTTP Header来指定需要饥饿加载的属性路径,但这是另一个问题。总之,在接下来的案例中,你将看到,虽然数据已经添加成功,但在返回的结果里,被聚合的子对象将无法返回。我会设法解决这个问题。

案例:Customer Service

假设我们需要使用Entity Framework快速构建一个支持增删改查操作的数据服务(Data Service),并希望该服务能够在容器中运行,我们可以首先新建一个ASP.NET Core的应用程序,然后依照下面的步骤进行:

  1. 向ASP.NET Core应用程序添加以下NuGet包引用:

    • Apworks.Integration.AspNetCore

    • Apworks.Repositories.EntityFramework

    • Microsoft.EntityFrameworkCore.SqlServer(在本案例中我们使用SQL Server,当然也可以使用PostgreSQL或者MySQL等)

    • Microsoft.EntityFrameworkCore.Tools

  2. 新建领域模型,向ASP.NET Core应用程序中添加Customer和Address类: 


    public  class  Address
    {
         public  Guid Id { get ; set ; }
         public  string  Country { get ; set ; }
         public  string  State { get ; set ; }
         public  string  City { get ; set ; }
         public  string  Street { get ; set ; }
         public  string  ZipCode { get ; set ; }
    }
    public  class  Customer : IAggregateRoot<Guid>
    {
         public  Guid Id { get ; set ; }
         public  string  Name { get ; set ; }
         public  string  Email { get ; set ; }
         public  Address ContactAddress { get ; set ; }
    }
    <font face= "Calibri" ></font>
  3. 新建一个DbContext类,用于指定数据库的访问方式,以及对模型对象/数据表结构进行映射: 


    public  class  CustomerDbContext : DbContext
    {
         public  DbSet<Customer> Customers { get ; set ; }
         protected  override  void  OnModelCreating(ModelBuilder modelBuilder)
         {
             modelBuilder.Entity<Customer>()
                 .ToTable( "Customers" )
                 .HasKey(x => x.Id);
             modelBuilder.Entity<Customer>()
                 .Property(x => x.Id)
                 .ForSqlServerHasDefaultValueSql( "newid()" );
             modelBuilder.Entity<Customer>()
                 .Property(x => x.Name)
                 .IsUnicode()
                 .IsRequired()
                 .HasMaxLength(20);
             modelBuilder.Entity<Customer>()
                 .Property(x => x.Email)
                 .IsUnicode()
                 .IsRequired()
                 .HasMaxLength(50);
             modelBuilder.Entity<Address>()
                 .ToTable( "Addresses" )
                 .HasKey(x => x.Id);
             modelBuilder.Entity<Address>()
                 .Property(x => x.Id)
                 .ForSqlServerHasDefaultValueSql( "newid()" );
             base .OnModelCreating(modelBuilder);
         }
         protected  override  void  OnConfiguring(DbContextOptionsBuilder optionsBuilder)
         {
             optionsBuilder.UseSqlServer( @"Server=localhost\sqlexpress; Database=CustomerService; Integrated Security=SSPI;" );
         }
    }
    <font face= "Calibri" ></font>
  4. 打开Package Manager Console,并在解决方案资源管理器中将当前ASP.NET Core项目设置为启动项目(注意:这一点非常重要)。然后依次执行: 


    Add-Migration InitialCreate
    Update-Database

    成功完成这一步骤后,我们的数据库就已经准备好了。事实上,以上步骤都是开发一个Entity Framework Core应用程序所必须经历的标准步骤,目前还没有用到Apworks的功能(当然,将Customer定义成聚合根除外)。接下来,我们开始实现并配置Apworks数据服务,接下来的步骤跟基于MongoDB的实现非常类似。 

  5. 在ASP.NET Core应用程序的Controllers文件夹下,新建一个CustomersController,从DataServiceController继承: 


    public  class  CustomersController : DataServiceController<Guid, Customer>
    {
         public  CustomersController(IRepositoryContext repositoryContext) : base (repositoryContext)
         {
         }
    }


  6. 打开Startup.cs文件,分别修改ConfigureServices和Configure方法,如下: 


    // This method gets called by the runtime. Use this method to add services to the container.
    public  void  ConfigureServices(IServiceCollection services)
    {
         // Add framework services.
         services.AddMvc();
         services.AddScoped<CustomerDbContext>();
         services.AddApworks()
             .WithDataServiceSupport( new  DataServiceConfigurationOptions(sp =>
                 new  EntityFrameworkRepositoryContext(sp.GetService<CustomerDbContext>())))
             .Configure();
    }
    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public  void  Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
         loggerFactory.AddConsole(Configuration.GetSection( "Logging" ));
         loggerFactory.AddDebug();
         app.EnrichDataServiceExceptionResponse();
         app.UseMvc();
    }


    与MongoDB实现不同的是,在使用EntityFrameworkRepositoryContext之前,我们需要通过services.AddScoped方法,将CustomerDbContext以Scoped生命周期注册到IoC容器中,而在初始化EntityFrameworkRepositoryContext时,使用Service Provider的GetService方法进行Resolve,这样就能确保每次HTTP请求完成时,资源都能成功释放。 

下面,我们来测试一下这个Apworks数据服务。在Visual Studio 2017中按下Ctrl+F5,直接运行ASP.NET Core应用程序,使用你喜欢的RESTful客户端软件,向/api/Customers进行POST操作,可以看到,Customer可以被成功创建,Customer Id即刻返回:

让我们再GET一下试试(注意:返回的ContactAddress是null,而事实上数据库里是有值的。这里返回null的原因是因为我们没有在Entity Framework中通过Include调用进行饥饿加载(Eager Loading),接下来会尝试解决这个问题):

除了ContactAddress在GET请求中返回为null之外,其它各种行为,包括数据服务所支持的API接口、调用方式等,都与之前MongoDB的实现完全相同。

源代码

本文案例中的源代码可以在Apworks Examples开源项目中找到。本案例的源代码在Apworks.Examples.CustomerService.EntityFramework目录下。

总结

本文带领着大家一起预览了Apworks数据服务对Entity Framework Core的支持,使得Apworks数据服务不仅可以使用MongoDB等NoSQL存储方案,也可以使用关系型数据库存储方案,而且编程体验也是几乎相同的。这对于不同应用场景下微服务的实现是非常有帮助的。虽然在Entity Framework Core的实现中,目前有些瑕疵,但我会尽快解决这个问题。

相关文章: 

  • 使用Angular 4、Bootstrap 4、TypeScript和ASP.NET Core开发的Apworks框架案例应用

  • 在ASP.NET Core中使用Apworks开发数据服务:对HAL的支持

  • 在ASP.NET Core中使用Apworks快速开发数据服务

  • NET Core中使用Irony实现自己的查询语言语法解析器

原文地址:http://www.cnblogs.com/daxnet/p/7157896.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324666.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

再有人问你Java内存模型是什么,就把这篇文章发给他

转载自 再有人问你Java内存模型是什么&#xff0c;就把这篇文章发给他 前几天&#xff0c;发了一篇文章&#xff0c;介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型&#xff0c;是这三个知识…

SpringMVC对Ajax请求的处理

SpringMVC对Ajax请求的处理 [1] 问题: 当浏览器发起一个ajax请求给服务器&#xff0c;服务器调用对应的单元方法处理ajax请求。 而ajax的请求在被处理完成后&#xff0c;其处理结果需要直接响应。而目前我们在单元方 法中响应ajax请求&#xff0c;使用的是response对象&#x…

ssl2344P2835-刻录光盘【Floyd,联通块数,图论】

正题 洛谷题目 就是给出一个图&#xff0c;求最小联通块数。 输入输出&#xff08;需要自取&#xff09; Input 先是一个数N&#xff0c;接下来N行&#xff0c;分别表示各个营员愿意把自己获得的资料拷贝给其他哪些营员。即输入数据的第N1行表示第i个营员愿意把资料拷贝给那…

为了金秋那沉甸甸的麦穗,我绝不辜负春天

本文原创&#xff1a;焦文宇我可以一落千丈&#xff0c;但我就是要一鸣惊人。——题记01 没有谁的一生是一帆风顺的&#xff0c;也没有谁的一生是充满坎坷的。人生就像是一场游戏“玩”的好坏全都在于自己&#xff0c;我们没有任何理由去抱怨生活中的点滴&#xff0c;我们应当对…

BigDecimal丢失精度的坑

问题&#xff1a;new BigDecimal(double d)的数值居然还是不精确的 double d 0.09; BigDecimal bigDecimalnew BigDecimal(d); System.out.println(bigDecimal); System.out.println(d); 输出结果&#xff1a; 0.0899999999999999966693309261245303787291049957275390625 …

编译型语言VS解释型语言

编译型语言人类代码 ————》一次性把代码给 翻译官&#xff08;编译器&#xff09;————》汇编--》机器语言代表 &#xff1a; c,c,golang优点&#xff1a;执行速度快缺点&#xff1a;跨平台可移植性差硬件 &#xff0c; cpu , 有自己指令规则 0000000001 打印&#xf…

P1236-Network of Schools(学校网络)【最强联通块,Kosaraju】

正题 POJ题目链接 给出一个图&#xff0c;求联通块数量和加入多少条边后会将全图变为一个最强联通块。 机翻输入输出&#xff08;需要自取&#xff09; 输入 第一行包含整数N&#xff1a;网络中的学校数量&#xff08;2 < N < 100&#xff09;。学校由前N个正整数标识…

限时团购,6.9折:《微信开发深度解析:公众号、小程序高效开发秘籍》推荐序

全书由目 Senparc.Weixin SDK 作者苏震巍历时 2 年完成&#xff0c;涵盖了开发微信公众号及小程序需要用的的各项后端开发技能、技巧、避坑提示&#xff0c;以及 Senparc.Weixin SDK 微信公众号及小程序模块全面的使用说明及原理剖析。 Senparc.Weixin SDK 发布 4 年多来&#…

SSM框架知识点复习

第三节 SSM框架知识点复习 SpringMVC的知识 技能:使用SpringMVC来处理浏览器发起的请求。 ① SpringMVC的基本使用流程 i. 导入jar包 ii. 配置SpringMVC的配置文件 iii. 配置web.xml文件 iv. 创建控制器类并声明单元方法 ② SpringMVC的单元方法获取请求 i. 使用形参名和键名一…

某同学工作之后的感悟

本文原创&#xff1a;王梦茹以下是王梦茹同学在学习中和工作中的感悟。01学习中出来之后发现在学校的学习效率是远远比自主学习效率高的&#xff0c;学什么东西之前都会先知道他的大体概念&#xff0c;通透了解一下再学习会发现有效率的多。在有大致了解的情况下再去听老师讲课…

“半路出家”的程序猿怎么不被“熊”

文本原创&#xff1a;孙浩投稿这篇文章总有点‘好为人师’的感觉&#xff0c;但是自己作为一个“半路出家”的程序看过太多的和我同样出身的程序半途而废了。我现在在一家软件公司就职&#xff0c;担任技术主管职位。01 带过毕业生&#xff0c;也带过中途转行&#xff0c;也带过…

这可能是把Docker的概念讲的最清楚的一篇文章

转载自 这可能是把Docker的概念讲的最清楚的一篇文章 Docker 是世界领先的软件容器平台&#xff0c;本文主要来介绍下关于Docker的那些事儿&#xff0c;主要包含以下内容&#xff1a; 容器 什么是Docker&#xff1f; Docker思想、特点 Docker容器主要解决什么问题 容器 V…

【2018.3.17】模拟赛之一-ssl2574jzoj1368 无限序列【斐波那契数列】

正题 链接 需要纪中OJ账号 刚开始一个字符串”1”。然后进行无数次变化&#xff0c;1变为10,0变为1。然后求多个区间内的1的个数 输入输出&#xff08;需要自取&#xff09; Input   第一行为一个整数Q&#xff0c;后面有Q行&#xff0c;每行两个数用空格隔开的整数a, b。 …

Python变量名的定义规则与定义方式

变量名的定义规则 1.变量名只能是 字母、数字或者下划线的任意组合 2.变量名的第一个字符不能是数字 3.一下关键字不能声明为变量名 常用定义方式 驼峰法 AgeOfOld56 NumberOfStudents22 下划线 age_of_old56 第二种为官方推荐 定义变量不好的方式举例 1.变量名为中…

洋葱架构简介——分离是为了更好的结合

写出高质量软件是困难和复杂的&#xff1a;不仅仅是为了满足需求&#xff0c;还应该是健壮的&#xff0c;可维护的&#xff0c;可测试的&#xff0c;并且足够灵活以适应成长和变化。这就是洋葱架构出现的原因&#xff0c;它代表一组优秀的开发实践&#xff0c;用来开发任何的软…

RBAC(基于角色的权限访问控制)

第一节.RBAC简介 英文全称(Role-Based Access Control)中文全称:基于角色的权限访问控制rbac: 一种数据库设计思想,根据设计数据库设计方案,完成项目的权限控制.经常需要添加权限的情景 4.1 不同用户登录后看到的菜单是不一样的. 4.2 不同用户看到的页面效果不一样 4.2.1 有的…

子列表只是原列表的一个视图

原文参考&#xff1a;《编写高质量代码&#xff1a;改善java程序的151个建议》本文原创&#xff1a;穆雄雄上期文章&#xff1a;subList?? subString???上期我们说到&#xff0c;List接口提供了subList方法&#xff0c;其作用是返回一个列表的子列表。并且我们通过案例说明…

python注释的用法(单and多行)

单行注释 # name"asdfdasfdas"多行注释 """ print(xy) aad2"""快捷键 先选中要注释的内容然后Ctrl/

【2018.3.17】模拟赛之二-ssl1862jzoj1366 删数【区间dp】

正题 链接 需要纪中OJ账号 有n个数&#xff0c;可以选择删除一段区间&#xff0c;价值为|xi – xk|*(k-i1)。求删完所有数的最大价值 输入输出&#xff08;需要自取&#xff09; Input    输入文件的第一行为一个正整数N&#xff0c;第二行有N个用空格隔开的N个不同的正整…

ASP.NET Core之跨平台的实时性能监控

前言 前面我们聊了一下一个应用程序 应该监控的8个关键位置. 应用程序的8个关键性能指标以及测量方法 最后卖了个小关子,是关于如何监控ASP.NET Core的. 今天我们就来讲讲如何监控它,下面上效果图: 阅读本文需要了解的相关技术与内容: InfluxDb(分布式时序数据库,开源)(注…