第 5 章 使用 Entity Framework Core

5.3 重构仓储类

创建一个通用仓储接口

namespace Library.API.Services
{
public interface IRepositoryBase<T>
{
Task<IEnumerable<T>> GetAllAsync();
Task<IEnumerable<T>> GetByConditionAsync(Expression<Func<T, bool>> expression);
void Create(T entity);
void Update(T entity);
void Delete(T entity);
Task<bool> SaveAsync();
}
}

继续创建一个接口

namespace Library.API.Services
{
public interface IRepositoryBase2<T,TId>
{
Task<T> GetByIdAsync(TId id);
Task<bool> IsExistAsync(TId id);
}
}

添加 RepositoryBase 类并实现上面两个接口

namespace Library.API.Services
{
public class RepositoryBase<T, TId> : IRepositoryBase<T>, IRepositoryBase2<T, TId> where T : class
{
public DbContext DbContext { get; set; } public RepositoryBase(DbContext dbContext)
{
DbContext = dbContext;
} public Task<IEnumerable<T>> GetAllAsync()
{
return Task.FromResult(DbContext.Set<T>().AsEnumerable());
} public Task<IEnumerable<T>> GetByConditionAsync(Expression<Func<T, bool>> expression)
{
return Task.FromResult(DbContext.Set<T>().Where(expression).AsEnumerable());
} public void Create(T entity)
{
DbContext.Set<T>().Add(entity);
} public void Update(T entity)
{
DbContext.Set<T>().Update(entity);
} public void Delete(T entity)
{
DbContext.Set<T>().Remove(entity);
} public async Task<bool> SaveAsync()
{
return await DbContext.SaveChangesAsync() > 0;
} public async Task<T> GetByIdAsync(TId id)
{
return await DbContext.Set<T>().FindAsync(id);
} public async Task<bool> IsExistAsync(TId id)
{
return await DbContext.Set<T>().FindAsync(id) != null;
}
}
}

这里需要注意的是,EF Core 对于查询的执行采用延迟执行的方法,只有遇到了实际需要结果的操作,查询才会执行,这些操作包括以下几种类型:

  • 对结果使用 for 或 foreach 循环
  • 使用了 ToList()、ToArray() 和 ToDictionary() 等方法
  • 使用了 Single()、Count()、Average、First() 和 Max() 等方法

创建其他仓储接口

public interface IAuthorRepository : IRepositoryBase<Author>, IRepositoryBase2<Author, Guid>

创建实现类

namespace Library.API.Services
{
public class AuthorRepository : RepositoryBase<Author, Guid>, IAuthorRepository
{
public AuthorRepository(DbContext dbContext) : base(dbContext)
{
}
}
}

以同样的方式创建 IBookRepository 与 BookRepository

接着创建仓储包装器 IRepositoryWrapper 及其实现

namespace Library.API.Services
{
public interface IRepositoryWrapper
{
IBookRepository Book { get; }
IAuthorRepository Author { get; }
}
} namespace Library.API.Services
{
public class RepositoryWrapper : IRepositoryWrapper
{
public LibraryDbContext LibraryDbContext { get; } private IAuthorRepository _authorRepository = null;
private IBookRepository _bookRepository = null; public RepositoryWrapper(LibraryDbContext libraryDbContext)
{
LibraryDbContext = libraryDbContext;
} public IAuthorRepository Author => _authorRepository ?? new AuthorRepository(LibraryDbContext);
public IBookRepository Book => _bookRepository ?? new BookRepository(LibraryDbContext);
}
}

包装器提供了所有仓储接口的统一访问方式,从而避免了单独访问每个仓储接口

接下来要将包装器放到容器中,在 ConfigureServices 注入

services.AddScoped<IRepositoryWrapper, RepositoryWrapper>();

5.4 重构 Controller 和 Action

在重构之前,引入对象映射库 AutoMapper

Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection

在 ConfigureServices 注入

services.AddAutoMapper(typeof(Startup));

为了 AutoMapper 正确执行对象映射,需要创建一个 Profile 类的派生类,用以说明映射的对象以及映射规则

namespace Library.API.Helpers
{
public class LibraryMappingProfile : Profile
{
public LibraryMappingProfile()
{
CreateMap<Author, AuthorDto>()
.ForMember(dest => dest.Age, config =>
config.MapFrom(src => src.BirthData.GetCurrentAge()));
CreateMap<Book, BookDto>();
CreateMap<AuthorForCreationDto, Author>();
CreateMap<BookForCreationDto, Book>();
CreateMap<BookForUpdateDto, Book>();
}
}
}

CreateMap 方法的两个泛型参数分别指明对象映射中的源和目标,当从数据库中获取数据时,实体类为源,而 DTO 为目标;当处理请求时相反

当程序运行时,执行 AddAutoMapper 方法时会扫描指定程序集中 Profile 类的派生类,并根据扫描结果生成映射规则

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

《ASP.ENT Core 与 RESTful API 开发实战》-- (第5章)-- 读书笔记(中)的更多相关文章

  1. 使用ASP.NET Core构建RESTful API的技术指南

    译者荐语:利用周末的时间,本人拜读了长沙.NET技术社区翻译的技术标准<微软RESTFul API指南>,打算按照步骤写一个完整的教程,后来无意中看到了这篇文章,与我要写的主题有不少相似之 ...

  2. 4类Storage方案(AS开发实战第四章学习笔记)

    4.1 共享参数SharedPreferences SharedPreferences按照key-value对的方式把数据保存在配置文件中,该配置文件符合XML规范,文件路径是/data/data/应 ...

  3. 菜单Menu(AS开发实战第四章学习笔记)

    4.5 菜单Menu Android的菜单主要分两种,一种是选项菜单OptionMenu,通过按菜单键或点击事件触发,另一种是上下文菜单ContextMenu,通过长按事件触发.页面的布局文件放在re ...

  4. [Android]《Android艺术开发探索》第一章读书笔记

    1. 典型情况下生命周期分析 (1)一般情况下,当当前Activity从不可见重新变为可见状态时,onRestart方法就会被调用. (2)当用户打开新的Activity或者切换到桌面的时候,回调如下 ...

  5. 温故知新,使用ASP.NET Core创建Web API,永远第一次

    ASP.NET Core简介 ASP.NET Core是一个跨平台的高性能开源框架,用于生成启用云且连接Internet的新式应用. 使用ASP.NET Core,您可以: 生成Web应用和服务.物联 ...

  6. 快读《ASP.NET Core技术内幕与项目实战》WebApi3.1:WebApi最佳实践

    本节内容,涉及到6.1-6.6(P155-182),以WebApi说明为主.主要NuGet包:无 一.创建WebApi的最佳实践,综合了RPC和Restful两种风格的特点 1 //定义Person类 ...

  7. 零基础ASP.NET Core WebAPI团队协作开发

    零基础ASP.NET Core WebAPI团队协作开发 相信大家对“前后端分离”和“微服务”这两个词应该是耳熟能详了.网上也有很多介绍这方面的文章,写的都很好.我这里提这个是因为接下来我要分享的内容 ...

  8. ASP.NET Core WebApi构建API接口服务实战演练

    一.ASP.NET Core WebApi课程介绍 人生苦短,我用.NET Core!提到Api接口,一般会想到以前用到的WebService和WCF服务,这三个技术都是用来创建服务接口,只不过Web ...

  9. 从 0 使用 SpringBoot MyBatis MySQL Redis Elasticsearch打造企业级 RESTful API 项目实战

    大家好!这是一门付费视频课程.新课优惠价 699 元,折合每小时 9 元左右,需要朋友的联系爱学啊客服 QQ:3469271680:我们每课程是明码标价的,因为如果售价为现在的 2 倍,然后打 5 折 ...

  10. Asp.Net Core 5 REST API - Step by Step

    翻译自 Mohamad Lawand 2021年1月19日的文章 <Asp.Net Core 5 Rest API Step by Step> [1] 在本文中,我们将创建一个简单的 As ...

随机推荐

  1. C# 加解密

    1.  Md5 /// <summary> /// 不可逆加密 /// 1 防止被篡改 /// 2 防止明文存储 /// 3 防止抵赖,数字签名 /// </summary> ...

  2. shell脚本(1)-shell介绍

    一.shell介绍 1.什么是shell shell是c语法编写的,是用户和liunx内核沟通的桥梁,即是命令语法,也是解释性编程语言. 内核处理的都是二进制,而用户处理的都是高级语法,系统开发人员可 ...

  3. Kafka 面试题

    1. 为什么要使用 Kafka,为什么要使用消息队列 1.使用消息队列的目的: 服务解耦 流量削峰 异步通信 在早期的 web 应用程序开发中,当请求量突然上来了时候,我们会将要处理的数据推送到一个队 ...

  4. ABP微服务系列学习-搭建自己的微服务结构(二)

    在解决方案根目录添加common.props,这个文件的作用是可以配置项目文件全局的一些属性,如忽略警告,全局PackageReference,语言版本等. <Project> <P ...

  5. Git-分支-branch-checkout-merge

  6. [转帖]分析redis 大key

    http://www.lishuai.fun/2023/05/05/redis-bigkey/#/%E5%AE%89%E8%A3%85 redis-rdb-tools 是一个 python 的解析 r ...

  7. [转帖]在龙芯3A5000上测试SPEC CPU 2006

    https://baijiahao.baidu.com/s?id=1707601012673143593&wfr=spider&for=pc 注:百家号中,一些文本.代码等的排版格式无 ...

  8. [转帖]记录几个常用linux命令的使用方法——find、grep、file、which、whereis和压缩命令gzip、bzip2、tar

    一.命令1: find.grep.file.which.whereis 1.find 目的:查找符合条件的文件 1)在哪些目录中查找 2)查找的内容 格式: find 目录名 选项 查找条件 举例: ...

  9. [转载]关于NSA的EternalBlue(永恒之蓝) ms17-010漏洞利用

    2017年5月19日   感谢原作者:http://www.cnblogs.com/cnbluerain/           好久没有用这个日志了,最近WannaCry横行,媒体铺天盖地的报道,我这 ...

  10. Object.defineProperty熬夜整理的用法,保证你看的明白!

    Object.defineProperty的基本使用 <script> let personObj={ name:'何西亚', sex:'男' } //我们想给这个对象添加一个属性 // ...