zoukankan      html  css  js  c++  java
  • 基于 EntityFramework 生成 Repository 模式代码

    借助 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

  • 相关阅读:
    在ASP.NET Core中使用TagHelpers
    ASP.NET Core使用Redis
    ASP.NET Core MVC中视图
    HTTP状态码
    ASP.NET Core中静态文件
    ASP.NET Core中使用依赖注入
    在ASP.NET Core中使用多个环境
    ASP.NET Core读取配置文件
    HTML+CSS解决高度塌陷和垂直重叠
    Element-UI的表格合计行的列添加操作按钮
  • 原文地址:https://www.cnblogs.com/weihanli/p/generate-entityframework-repository.html
Copyright © 2011-2022 走看看