借助 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. cordova+vue混合式开发App

    应要求第一次使用cordova打包了一下vue写的app项目,期间遇到了不少问题,整理一下流程并记录一下常见问题吧.        cordova打包项目需要的环境配置啥的就不具体讲啦,百度一下很多教 ...

  2. nlp英文的数据清洗代码

    1.常用的清洗方式 #coding=utf-8 import jieba import unicodedata import sys,re,collections,nltk from nltk.ste ...

  3. C++ std::array 基本用法

    #include <iostream> #include <string> #include <array> using namespace std; // htt ...

  4. 2019阿里天猫团队Java高级工程师面试题之第一面

    2019阿里天猫团队Java高级工程师面试题之第二面 2019阿里天猫团队Java高级工程师面试题之第三面 1.五分钟自我介绍,说说自己的擅长及拿手的技术 自我介绍是为了考察面试者的语言表达和总结概括 ...

  5. windows环境下Jmeter5.2的安装使用

    一.安装配置JDK Jmeter5.2依赖JDK1.8+版本,JDK安装百度搜索JAVA下载JDK,地址:https://www.oracle.com/technetwork/java/javase/ ...

  6. git commit vim报错

    window平台,使用git bash,填写git commit时,退出时vim报错: 错误信息 启动失败 Vim: Caught deadly signal SEGV 在工程目录下,进.git目录, ...

  7. VS2019 .Net Core 3.0 Web 项目启用动态编译

    VS2019 中 .Net Core 3.0 项目默认没有启用动态编译, 这导致按F5调试的时候,修改了 HTML 代码,在浏览器上刷新没有效果. 启用动态编译方法如下: 1. 安装 Microsof ...

  8. 如何在CAD图纸中进行线性标注

    在CAD中,都会在图纸中进行CAD标注,一般都是有CAD标注样式.CAD标注文字等.那其中有一个就是CAD线性标注?可以标注图纸间的距离?那如何在CAD图纸中进行线性标注呢?具体要怎么来进行操作?本篇 ...

  9. word-break、word-wrap、white-space区别

    <div id="box"> Hi  , This is a incomprehensibilities long word. </br> 你好  , 这 ...

  10. bay——RAC 表空间时数据文件误放置到本地文件系统-介质恢复.txt

    RAC添加新表空间时数据文件误放置到本地文件系统的修正 于是我想11G 也兼容这些操作的方法,但是11G的新特性有一点就是可以直接支持ASM文件系统直接可以和本地文件系统进行文件的拷贝了,也就是有三种 ...