借助 WeihanLi.EntityFramework 实现简单的 Repository

Intro

很多时候一些简单的业务都是简单的增删改查,动态生成一些代码完成基本的增删改查,而这些增删改查代码大多类似,只有一些有复杂业务逻辑的可能需要手动去写。于是实现了一个简单的基于 EF Core 的 Repository。

GetStarted

  1. 添加包引用

在项目里增加对 WeihanLi.EntityFramework 的引用

dotnet add package WeihanLi.EntityFramework

来看个使用例子

使用方式:

  1. 不需要定义自己的Repository,默认使用泛型的Repository
// 注册 EFREpository
services.AddEFRepostory(); // 在需要的地方使用,直接获取一个 `IEFRepository<TestDbContext, TestEntity>` 服务
DependencyResolver.Current.TryInvokeService<IEFRepository<TestDbContext, TestEntity>>(repo =>
{
repo.Update(new TestEntity
{
CreatedAt = DateTime.UtcNow,
Extra = new { Name = "Abcde", Count = 4 }.ToJson(),
Id = 3
}, t => t.CreatedAt, t => t.Extra);
repo.Insert(new[]
{
new TestEntity
{
Extra = new {Name = "Abcdes"}.ToJson(),
CreatedAt = DateTime.Now
},
new TestEntity
{
Extra = new {Name = "Abcdes"}.ToJson(),
CreatedAt = DateTime.Now
}
});
var list = repo.GetAll().Select(_ => _.Id).ToArray();
Console.WriteLine($"Ids: {list.StringJoin(",")}"); repo.Get(_ => _.Id, queryBuilder => queryBuilder
.WithOrderBy(q => q.OrderByDescending(_ => _.Id))); var lastItem = repo.FirstOrDefault(queryBuilder => queryBuilder
.WithOrderBy(q => q.OrderByDescending(_ => _.Id))); var list1 = repo.Get(x => x.Id, queryBuilder => queryBuilder
.WithOrderBy(query => query.OrderByDescending(q => q.Id))
); repo.Delete(t => DbFunctions.JsonValue(t.Extra, "$.Name") == "Abcdes");
Console.WriteLine($"Count: {repo.Count()}");
});
  1. 生成自己的 Repository 代码

你可以生成自己的 基于 默认的 Repository 的代码,默认的 Repository 的所有方法都是虚方法,可以重写也可以,默认会生成接口和类,如果不要生成接口可以配置 EFRepositoryGeneratorOptions

// 配置不生成接口
services.Configure<EFRepositoryGeneratorOptions>(options=>options.GenerateInterface=false); // 配置生成的 Repository 类型名称, 默认是 EntityName+"Repository",可以通过 RepositoryNameResolver 自定义
services.Configure<EFRepositoryGeneratorOptions>(options=>options.RepositoryNameResolver = entityName=> $"{entityName}Service");

默认生成的代码类似于这样子:

using WeihanLi.EntityFramework;
using WeihanLi.EntityFramework.Samples; namespace WeihanLi.EntityFramework.Samples.Business
{ public partial interface ITestEntityRepository : IEFRepository<TestDbContext, TestEntity> { }
public partial class TestEntityRepository : EFRepository<TestDbContext, TestEntity>, ITestEntityRepository
{
public TestEntityRepository(TestDbContext dbContext) : base(dbContext) { }
}
}

如果对生成的代码内容部分要修改,可以自定义自己的 IEFRepositoryGenerator,然后 services.AddSingleton<IEFRepositoryGenerator, CustomEFRepositoryGenerator>() 覆盖掉默认的就可以了,或者可以 Replace 直接替换也是可以的~

调用下面的代码去生成代码:

DependencyResolver.Current.ResolveService<IEFRepositoryGenerator>()
.GenerateRepositoryCodeFor<TestDbContext>("WeihanLi.EntityFramework.Samples.Business");

QueryBuilder 使用

为 EF 添加了 FluentAPI 的 QueryBuilder 支持,使得可以更方便的进行数据查询。

默认的 QueryBuilder 会 AsNoTracking(),如果不要 AsNoTracking可以使用 WithNoTracking(false) 来设置,EFCore 新增了一个 QueryFilter 可以全局过滤,默认查询也是启动全局过滤的,如果要在查询中禁用这个全局过滤可以通过 IgnoreQueryFilters() 来设置。

基本方法:

EFRepositoryQueryBuilder<TEntity> WithPredict(Expression<Func<TEntity, bool>> predict);// 设置查询条件
EFRepositoryQueryBuilder<TEntity> WithOrderBy(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderByExpression); // 设置排序
EFRepositoryQueryBuilder<TEntity> WithNoTracking(bool noTracking = true); // 设置是否 Tracking
EFRepositoryQueryBuilder<TEntity> IgnoreQueryFilters(bool ignoreQueryFilters = true);// 是否忽略查询
EFRepositoryQueryBuilder<TEntity> WithInclude(Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include); // 设置 include
EFRepositoryQueryBuilder<TEntity> WithCount(int count);// 如果要查 Top N 的时候可以设置

使用示例如下:

var repository = serviceProvider.GetService<IEFRepository<TestDbContext, TestEntity>>();

// query lastItem
var lastItem = repo.FirstOrDefault(queryBuilder => queryBuilder
.WithOrderBy(q => q.OrderByDescending(_ => _.Id))); // query id list orderBy id desending
var idList = repo.Get(x => x.Id, queryBuilder => queryBuilder
.WithOrderBy(query => query.OrderByDescending(q => q.Id))
); var blockList = serviceProvider.GetService<IEFRepository<TestDbContext, BlockEntity>>().GetPagedList(queryBuilder => queryBuilder
.WithPredict(whereLambda)
.WithInclude(q => q.Include(b => b.BlockType))
.WithOrderBy(q => q.OrderByDescending(b => b.BlockTime)), search.PageIndex, search.PageSize); //load data
var list = _reservationBLL.GetPagedList(queryBuilder => queryBuilder
.WithPredict(whereLambda)
.WithOrderBy(query => query.OrderByDescending(r => r.ReservationForDate).ThenByDescending(r => r.ReservationTime))
.WithInclude(query => query.Include(r => r.Place))
, search.PageIndex, search.PageSize);

部分更新

来看下面的示例:

repo.Update(new TestEntity
{
Extra = new { Name = "Abcde", Count = 4 }.ToJson(),
CreatedAt = DateTime.UtcNow,
Id = 1
}, t => t.CreatedAt, t => t.Extra); // 更新 CreatedAt 和 Extra 字段 repo.UpdateWithout(new TestEntity() { Id = 2, Extra = new { Name = "ADDDDD" }.ToJson() }, x => x.CreatedAt); // 更新 CreatedAt 之外的其他字段

Reference

基于 EntityFramework 生成 Repository 模式代码的更多相关文章

  1. GIAC2019 演讲精选 | 面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码

    一直以来, 如何从‘视觉稿’精确的还原出 对应的UI侧代码 一直是端侧开发同学工作里消耗比较大的部分,一方面这部分的工作 比较确定缺少技术深度,另一方面视觉设计师也需要投入大量的走查时间,有大量无谓的 ...

  2. 【温故知新】C#基于事件的异步模式(EAP)

    在开发winform和调用asp.net的web service引用的时候,会出现许多命名为 MethodNameAsync 的方法. 例如: winform的按钮点击 this.button1.Cl ...

  3. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

  4. EntityFramework系列:Repository模式与单元测试

    1.依赖IRepository接口而不是直接使用EntityFramework 使用IRepository不只是架构上解耦的需要,更重要的意义在于Service的单元测试,Repository模式本身 ...

  5. 基于Repository模式设计项目架构—你可以参考的项目架构设计

    关于Repository模式,直接百度查就可以了,其来源是<企业应用架构模式>.我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repos ...

  6. 分享基于EF6、Unitwork、Autofac的Repository模式设计

    目录 分享基于EF6.Unitwork.Autofac的Repository模式设计 一.实现的思路和结构图 二.Repository设计具体的实现代码 三.Repository设计的具体的使用 四. ...

  7. 分享基于Entity Framework的Repository模式设计(附源码)

    关于Repository模式,在这篇文章中有介绍,Entity Framework返回IEnumerable还是IQueryable? 这篇文章介绍的是使用Entity Framework实现的Rep ...

  8. 基于eclipse的mybatis映射代码自动生成的插件

    基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...

  9. 基于eclipse的mybatis映射代码自动生成的插件http://blog.csdn.net/fu9958/article/details/7521681

    基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...

随机推荐

  1. MongoDB学习笔记(七、MongoDB总结)

    1.为什么要NoSQL:nosql能解决sql中那些解决不了的问题 NoSQL是什么:Not Only SQL,本质上还是数据库,但它不会遵循传统数据库的规则(如:SQL标准.ACID属性[事务].表 ...

  2. STM32基本GPIO操作:点灯(库函数+寄存器)

    社团作业=_= 开发版上的LED灯负极连接在PB5口,正极串联一510Ω电阻后与3.3V相连 若开发板不带LED灯则需要自行连接,务必串联一个合适的电阻防止LED灯烧坏 零.一个有趣的延时函数 来自于 ...

  3. IPv6升级测试指南(Android/iOS/Mac)

    目录 我们升级到IPv6的原因 测试的时候的注意要点 Android/IOS/MAC测试总结 Android测试IPv6的方法 IOS端测试IPv6的方法 MAC浏览器端测试IPv6的方法 升级IPV ...

  4. Redis令牌桶限流

    一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...

  5. jQuery-跨域问题的处理

    调用登录接口时,后端一般会在调用登录接口成功后,在response中设置cookie,之后前端的每次请求都会自动地在请求头上加上后端设置好的cookie,这对前端来说是透明的. 当登录接口与登录后调用 ...

  6. 多线程六 同步容器&并发容器

    同步容器(使用的是synchronized,并且不一定是百分百安全) 本篇续 -- 线程之间的通信 ,介绍java提供的并发集合,既然正确的使用wait和notify比较困难,java平台为我们提供了 ...

  7. Selenium(十五):unittest单元测试框架(一) 初识unittest

    1. 认识unittest 什么是单元测试?单元测试负责对最小的软件设计单元(模块)进行验证,它使用软件设计文档中对模块的描述作为指南,对重要的程序分支进行测试以发现模块中的错误.在python语言下 ...

  8. 用html,CSS 写一个静态的博客网页

    <!doctype html> <html> <br/><br/><br/> <head> <meta http-equi ...

  9. 大话Git系列之初识版本控制系统(1)

    前言:何谓版本控制系统呐?有两种说法:一种叫法为SCM,==source code management (源代码管理系统)另一种说法为VCS,==version control system(版本控 ...

  10. 23种设计模式之Builder设计模式

    概述 建造者模式(Builder Pattern),是创造性模式之一,Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在 ...