当前位置: 代码迷 >> 综合 >> 基于 EntityFramework 生成 Repository 模式代码
  详细解决方案

基于 EntityFramework 生成 Repository 模式代码

热度:86   发布时间:2024-01-12 10:58:01.0

借助 WeihanLi.EntityFramework 实现简单的 Repository

Intro

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

GetStarted

0. 添加包引用

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

dotnet add package WeihanLi.EntityFramework

来看个使用例子:

使用方式:

1. 不需要定义自己的Repository,默认使用泛型的Repository

 
  
  1. // 注册 EFREpository

  2. services.AddEFRepostory();


  3. // 在需要的地方使用,直接获取一个 `IEFRepository<TestDbContext, TestEntity>` 服务

  4. DependencyResolver.Current.TryInvokeService<IEFRepository<TestDbContext, TestEntity>>(repo =>

  5. {

  6. repo.Update(new TestEntity

  7. {

  8. CreatedAt = DateTime.UtcNow,

  9. Extra = new { Name = "Abcde", Count = 4 }.ToJson(),

  10. Id = 3

  11. }, t => t.CreatedAt, t => t.Extra);

  12. repo.Insert(new[]

  13. {

  14. new TestEntity

  15. {

  16. Extra = new { Name = "Abcdes"}.ToJson(),

  17. CreatedAt = DateTime.Now

  18. },

  19. new TestEntity

  20. {

  21. Extra = new { Name = "Abcdes"}.ToJson(),

  22. CreatedAt = DateTime.Now

  23. }

  24. });

  25. var list = repo.GetAll().Select(_ => _.Id).ToArray();

  26. Console.WriteLine($"Ids: {list.StringJoin(",")}");


  27. repo.Get(_ => _.Id, queryBuilder => queryBuilder

  28. .WithOrderBy(q => q.OrderByDescending(_ => _.Id)));


  29. var lastItem = repo.FirstOrDefault(queryBuilder => queryBuilder

  30. .WithOrderBy(q => q.OrderByDescending(_ => _.Id)));


  31. var list1 = repo.Get(x => x.Id, queryBuilder => queryBuilder

  32. .WithOrderBy(query => query.OrderByDescending(q => q.Id))

  33. );


  34. repo.Delete(t => DbFunctions.JsonValue(t.Extra, "$.Name") == "Abcdes");

  35. Console.WriteLine($"Count: {repo.Count()}");

  36. });

2. 生成自己的 Repository 代码

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

 
  
  1. // 配置不生成接口

  2. services.Configure<EFRepositoryGeneratorOptions>(options=>options.GenerateInterface=false);


  3. // 配置生成的 Repository 类型名称, 默认是 EntityName+"Repository",可以通过 RepositoryNameResolver 自定义

  4. services.Configure<EFRepositoryGeneratorOptions>(options=>options.RepositoryNameResolver = entityName=> $"{entityName}Service");

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

 
  
  1. using WeihanLi.EntityFramework;

  2. using WeihanLi.EntityFramework.Samples;


  3. namespace WeihanLi.EntityFramework.Samples.Business

  4. {


  5. public partial interface ITestEntityRepository : IEFRepository<TestDbContext, TestEntity> { }

  6. public partial class TestEntityRepository : EFRepository<TestDbContext, TestEntity>, ITestEntityRepository

  7. {

  8. public TestEntityRepository(TestDbContext dbContext) : base(dbContext) { }

  9. }

  10. }

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

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

 
  
  1. DependencyResolver.Current.ResolveService<IEFRepositoryGenerator>()

  2. .GenerateRepositoryCodeFor<TestDbContext>("WeihanLi.EntityFramework.Samples.Business");

QueryBuilder 使用

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

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

基本方法:

 
  
  1. EFRepositoryQueryBuilder<TEntity> WithPredict(Expression<Func<TEntity, bool>> predict);// 设置查询条件

  2. EFRepositoryQueryBuilder<TEntity> WithOrderBy(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderByExpression); // 设置排序

  3. EFRepositoryQueryBuilder<TEntity> WithNoTracking(bool noTracking = true); // 设置是否 Tracking

  4. EFRepositoryQueryBuilder<TEntity> IgnoreQueryFilters(bool ignoreQueryFilters = true);// 是否忽略查询

  5. EFRepositoryQueryBuilder<TEntity> WithInclude(Func<IQueryable<TEntity>, IIncludableQueryable<TEntity, object>> include); // 设置 include

  6. EFRepositoryQueryBuilder<TEntity> WithCount(int count);// 如果要查 Top N 的时候可以设置

使用示例如下:

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


  2. // query lastItem

  3. var lastItem = repo.FirstOrDefault(queryBuilder => queryBuilder

  4. .WithOrderBy(q => q.OrderByDescending(_ => _.Id)));


  5. // query id list orderBy id desending

  6. var idList = repo.Get(x => x.Id, queryBuilder => queryBuilder

  7. .WithOrderBy(query => query.OrderByDescending(q => q.Id))

  8. );


  9. var blockList = serviceProvider.GetService<IEFRepository<TestDbContext, BlockEntity>>().GetPagedList(queryBuilder => queryBuilder

  10. .WithPredict(whereLambda)

  11. .WithInclude(q => q.Include(b => b.BlockType))

  12. .WithOrderBy(q => q.OrderByDescending(b => b.BlockTime)), search.PageIndex, search.PageSize);


  13. //load data

  14. var list = _reservationBLL.GetPagedList(queryBuilder => queryBuilder

  15. .WithPredict(whereLambda)

  16. .WithOrderBy(query => query.OrderByDescending(r => r.ReservationForDate).ThenByDescending(r => r.ReservationTime))

  17. .WithInclude(query => query.Include(r => r.Place))

  18. , 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


 
  

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg



  相关解决方案