基于 EntityFramework 生成 Repository 模式代码
借助 WeihanLi.EntityFramework 实现简单的 Repository
Intro
很多时候一些简单的业务都是简单的增删改查,动态生成一些代码完成基本的增删改查,而这些增删改查代码大多类似,只有一些有复杂业务逻辑的可能需要手动去写。于是实现了一个简单的基于 EF Core 的 Repository。
GetStarted
- 添加包引用
在项目里增加对 WeihanLi.EntityFramework 的引用
dotnet add package WeihanLi.EntityFramework
来看个使用例子:
使用方式:
- 不需要定义自己的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()}");
});
- 生成自己的 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
- https://github.com/WeihanLi/ActivityReservation/blob/dev/ActivityReservation/Controllers/HomeController.cs#L43
- https://github.com/WeihanLi/ActivityReservation/blob/dev/ActivityReservation.AdminLogic/Controllers/BlockEntityController.cs#L39
- https://github.com/WeihanLi/WeihanLi.EntityFramework/blob/dev/samples/WeihanLi.EntityFramework.Samples/Program.cs
基于 EntityFramework 生成 Repository 模式代码的更多相关文章
- GIAC2019 演讲精选 | 面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码
一直以来, 如何从‘视觉稿’精确的还原出 对应的UI侧代码 一直是端侧开发同学工作里消耗比较大的部分,一方面这部分的工作 比较确定缺少技术深度,另一方面视觉设计师也需要投入大量的走查时间,有大量无谓的 ...
- 【温故知新】C#基于事件的异步模式(EAP)
在开发winform和调用asp.net的web service引用的时候,会出现许多命名为 MethodNameAsync 的方法. 例如: winform的按钮点击 this.button1.Cl ...
- 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获
项目开发中的一些注意事项以及技巧总结 1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...
- EntityFramework系列:Repository模式与单元测试
1.依赖IRepository接口而不是直接使用EntityFramework 使用IRepository不只是架构上解耦的需要,更重要的意义在于Service的单元测试,Repository模式本身 ...
- 基于Repository模式设计项目架构—你可以参考的项目架构设计
关于Repository模式,直接百度查就可以了,其来源是<企业应用架构模式>.我们新建一个Infrastructure文件夹,这里就是基础设施部分,EF Core的上下文类以及Repos ...
- 分享基于EF6、Unitwork、Autofac的Repository模式设计
目录 分享基于EF6.Unitwork.Autofac的Repository模式设计 一.实现的思路和结构图 二.Repository设计具体的实现代码 三.Repository设计的具体的使用 四. ...
- 分享基于Entity Framework的Repository模式设计(附源码)
关于Repository模式,在这篇文章中有介绍,Entity Framework返回IEnumerable还是IQueryable? 这篇文章介绍的是使用Entity Framework实现的Rep ...
- 基于eclipse的mybatis映射代码自动生成的插件
基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...
- 基于eclipse的mybatis映射代码自动生成的插件http://blog.csdn.net/fu9958/article/details/7521681
基于eclipse的mybatis映射代码自动生成的插件 分类: JAVA 数据库 工具相关2012-04-29 00:15 2157人阅读 评论(9) 收藏 举报 eclipsegeneratori ...
随机推荐
- vue element-ui父列表和子列表同时出现时的bug
在项目中遇到这样的问题 当第一个父列表下的子列表选择了1,切换到第二个父列表的时候,也会默认选择1 我最开始是计划通过修改子列表的default-active为-1,结果不行 后来发现出现这个问题的原 ...
- 剑指Offer-42.和为S的两个数字(C++/Java)
题目: 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. 分析: ...
- [译]Vulkan教程(19)渲染和呈现
[译]Vulkan教程(19)渲染和呈现 Rendering and presentation 渲染和呈现 Setup 设置 This is the chapter where everything ...
- C# LINQ Join两个表连接,关联多个条件的写法
1.sql语句: select * from Users u join Teachers t on u.UserID==t.TeacherID and u.Name=t.Name 2.linq写法: ...
- swoole视频直播
$serv=new swoole_websocket_server("0.0.0.0",9501);$client=array();$serv->on("open& ...
- IT兄弟连 HTML5教程 多媒体应用 小结及习题
小结 在互联网上,图像和链接则是通过URL唯一确定信息资源的位置.URL分为绝对URL和相对URL.通过使用<img />标记在浏览器中显示一张图像.超文本具有的链接能力,可层层链接相关文 ...
- NuGet Install-Package 命令
例: Install-Package CefSharp.Wpf -Version 73.1.130 Install-Package CefSharp.Common -Version 73.1.130 ...
- GO基础之切片
一.什么是切片 Go语言切片是对数组的抽象. Go数组的长度不可改变,在特定场景中这样的集合就不太适用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"): 与数组相比切 ...
- mapreduce shortest way out
相关知识 最优路径算法是无向图中满足通路上所有顶点(除起点.终点外)各异,所有边也各异的通路.应用在公路运输中,可以提供起点和终点之间的最短路径,节省运输成本.可以大大提高交通运输效率. 本实验采用D ...
- 部署web01,web02,nfs,db01,backup,搭建wordpress,WeCenter,实现共享,热备,实时备份
小结 部署web01,web02,nfs,db01,backup,搭建wordpress,WeCenter,实现共享,热备,实时备份 1)在web01和web02上安装nginx和php 2)创建ww ...