借助 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);
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
黄山市民网:https://www.huangshanshimin.com/