借助 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. 【OCR技术系列之四】基于深度学习的文字识别

    上一篇提到文字数据集的合成,现在我们手头上已经得到了3755个汉字(一级字库)的印刷体图像数据集,我们可以利用它们进行接下来的3755个汉字的识别系统的搭建.用深度学习做文字识别,用的网络当然是CNN ...

  2. 【Unity游戏开发】Android6.0以上的动态权限申请问题

    一.引子 最近公司的游戏在做安全性测试,期间也暴露出了不少安全上的问题.虽然我们今天要说的权限申请和安全性相关不大,但是也会影响到游戏的使用体验等,所以本篇博客中马三就想和大家谈谈Android6.0 ...

  3. C语言结构选择语句

    总结一下常用的if else与switch,其中switch中的break知识点是笔试题经常考到的内容. if else与else if 在C语言中,经常使用if else选择语句,来实现很多对应的功 ...

  4. JavPlayer:AI破坏马赛克,大量马赛克破坏版影片流出

    这是最近几个月业界讨论比较火的话题,发酵到现在, 终于可以给大家总结下最近的马赛克破坏版影片到底是怎么回事? 马赛克破坏版,简单讲就是利用AI技术,在打有马赛克影片的马赛克基础上进行修复操作, 来实现 ...

  5. mysql给字段取别名无法被jdbc解析的解决办法

    项目上用的Spring JDBC,是通过ResultSetMetaData接口来调用具体数据库的JDBC实现类来获取数据库返回结果集的. 在项目开发中,发现在MySQL中使用的别名没有办法被正常解析, ...

  6. SpringCloud的入门学习之概念理解、Config配置中心

    1.SpringCloud Config分布式配置中心.分布式系统面临的配置问题. 答:微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务.由于每个 ...

  7. Evaluation Warning : The document was created with Spire.PDF for .NET.

    由于使用  Spire.Pdf 生成的书签带有 Evaluation Warning : The document was created with Spire.PDF for .NET. 字样 但是 ...

  8. vue.js+THREE.js演示服务端3D模型流程总结

    three.js官网 ·场景搭建 使用npm或者其他获取安装three,就像npm i three,之后在需要演示模型的vue组件内import * as THREE from 'three',此时我 ...

  9. 简单sql注入学到的延时盲注新式攻击

    0x01 知识点 mysql_pconnect(server,user,pwd,clientflag) mysql_pconnect() 函数打开一个到 MySQL 服务器的持久连接. mysql_p ...

  10. IaaS、PaaS、SaaS介绍(非原创)

    文章大纲 一.IaaS.PaaS.SaaS介绍与比较二.参考文章 一.IaaS.PaaS.SaaS介绍与比较 随着云计算.大数据.人工智能等一批新技术的涌入,企业信息化建设速度加快,基于云计算的Iaa ...