草庐IT

自动注册实体类到EntityFramework Core上下文,并适配ABP及ABP VNext

吉祥兴旺 2023-03-28 原文

继上篇文章(EF Core懒人小技巧之拒绝DbSet)之后,最近笔者把这个小功能单独封装成一个扩展方法并开源,欢迎交流和Star~

GitHub: EntityFrameworkCore.Extension.AutoMapping

Nuget:EntityFrameworkCore.Extension.AutoMapping

             EntityFrameworkCore.Extension.AutoMapping.Abp

             EntityFrameworkCore.Extension.AutoMapping.AbpVNext

如何使用

在DbContext.cs中重写OnModelCreating方法:

using EntityFrameworkCore.Extension;
... //此处省略其它代码
public class XmateDbContext:DbContext
{
  ... //此处省略其它代码
  protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
    var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
    modelBuilder.AutoMappingEntityTypes<IEntity>(modelAssemblyName);//泛型IEntity为所有实体类的规约类型
    base.OnModelCreating(modelBuilder);//这个必须加,否则报错
    
    ...//此处省略其它代码
  }
}

这样,我们就可以不用写满屏的DbSet了。
但是,在有的第三方框架中可能就会诞生新的问题。。。
比如在ABP或者VNext框架中,用过ABP框架的都应该知道,ABP是通过扫描DbContext中的DbSet来实现将实体类的仓储自动注册到IOC容器中的,下面我们就需要自己动手来实现:

    public static class AutoRegisterEntityRepositoryExtensions
    {
        /// <summary>
        /// 将数据表实体类型对应的仓储注入到IOC容器
        /// </summary>
        /// <param name="iocManager"></param>
        public static void RegisterDbEntityRepositories<TDbContext>(this IIocManager iocManager, string modelAssemblyName) where TDbContext : DbContext
        {
            foreach (var entityType in GetDbEntityType(typeof(IEntity<>), modelAssemblyName))
            {
                var keyType = entityType.GetInterfaces().Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEntity<>)).SelectMany(t => t.GetGenericArguments()).First();
                var genericRepositoryType = typeof(IRepository<,>).MakeGenericType(entityType, keyType);
                var impType = typeof(EfCoreRepositoryBase<,,>).MakeGenericType(typeof(TDbContext), entityType, keyType);
                iocManager.RegisterIfNot(genericRepositoryType, impType, lifeStyle: DependencyLifeStyle.Transient);
            }
        }

        /// <summary>
        /// 获取数据表实体类型列表
        /// </summary>
        /// <param name="constraintType">实体定义约束类型</param>
        /// <param name="modelAssemblyName">实体类所在dll名称,不包含后缀名(.dll)</param>
        /// <returns></returns>
        private static List<Type> GetDbEntityType(Type constraintType, string modelAssemblyName)
        {
            var all = AppDomain.CurrentDomain.GetAssemblies();
            var types = all.WhereIf(!modelAssemblyName.IsNullOrWhiteSpace(), a => a.FullName.Contains(modelAssemblyName))
                .SelectMany(m => m.GetTypes().Where(t => t.IsClass && !t.IsAbstract && (t.IsImplement(constraintType) || t.IsSubclass(constraintType))).ToList())
                .Distinct()
                .ToList();
            return types.Where(t => !t.GetCustomAttributes<NotMappedAttribute>().Any()).ToList();
        }
    }

注:以上代码摘自:AutoRegisterEntityRepositoryExtensions.cs

在ABP VNext中的实现思路也是如此,这里就不贴代码了,感兴趣的可以查阅源代码

在Abp中实现自动注入实体类对应的Repository

using EntityFrameworkCore.Extension.AutoMapping.Abp;
... //此处省略其它代码
public class XmateModule:AbpModule
{
  ... //此处省略其它代码
  //重写Initialize方法
  public override void Initialize()
  {
      ... //此处省略其它代码
      var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
      IocManager.RegisterDbEntityRepositories(modelAssemblyName);
  }
}

在Abp VNext中实现自动注入实体类对应的Repository

using EntityFrameworkCore.Extension.AutoMapping.AbpVNext;
... //此处省略其它代码
public class XmateModule:AbpModule
{
  ... //此处省略其它代码
  //重写ConfigureServices方法
  public override void ConfigureServices(ServiceConfigurationContext context)
  {
      ... //此处省略其它代码
      var modelAssemblyName = "XMate.Models";//实体类所在类库的名称,不包含扩展名(.dll)
      context.Services.RegisterDbEntityRepositories(modelAssemblyName);
  }
}

有关自动注册实体类到EntityFramework Core上下文,并适配ABP及ABP VNext的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  3. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  4. 阿里云国际版免费试用:如何注册以及注意事项 - 2

    作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。​关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐

  5. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  6. ruby - 在 Ruby 中,在类方法的上下文中,什么是实例变量和类变量? - 2

    如果我有以下一段Ruby代码:classBlahdefself.bleh@blih="Hello"@@bloh="World"endend@blih和@@bloh到底是什么?@blih是Blah类中的一个实例变量,@@bloh是Blah类中的一个类变量,对吗?这是否意味着@@bloh是Blah的类Class中的一个变量? 最佳答案 人们似乎忽略了该方法是类方法。@blih将是常量Bleh的类Class实例的实例变量。因此:irb(main):001:0>classBlehirb(main):002:1>defself.blehirb

  7. ruby-on-rails - 设计注册确认 - 2

    我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:

  8. ruby - 在 ruby​​ 中使用自动创建插入数组 - 2

    我想知道是否可以通过自动创建数组来插入数组,如果数组不存在的话,就像在PHP中一样:$toto[]='titi';如果尚未定义$toto,它将创建数组并将“titi”压入。如果已经存在,它只会推送。在Ruby中我必须这样做:toto||=[]toto.push('titi')可以一行完成吗?因为如果我有一个循环,它会测试“||=”,除了第一次:Person.all.eachdo|person|toto||=[]#with1billionofperson,thislineisuseless999999999times...toto.push(person.name)你有更好的解决方案吗?

  9. ruby - 在 Ruby 中的另一个上下文中评估潜在的相对 URI - 2

    我在Ruby程序中有两个URI。一个肯定是绝对URI,另一个可能是绝对URI或相对URI。我想在第一个的上下文中将第二个转换为绝对URI,所以如果第一个是http://pupeno.com/blog第二个是/about,结果应该是http://pupeno.com/about.有什么想法吗? 最佳答案 Ruby的内置URI和Addressablegem,做这个简短的工作。我更喜欢Addressable,因为它功能更全面,但URI是内置的。require'uri'URI.join('http://pupeno.com/blog','/

  10. ruby-on-rails - 特征未注册 : attribute name - 2

    完成这个有困难。我正在使用seed.rb+factory_girl来使用rakedb:seed填充数据库。(我知道固定装置存在,但我想以这种方式完成,这只是一个示例,数据库将填充复杂的关联对象。)我的种子.rb:require'factory_girl_rails'["QM","CDC","SI","QS"].eachdo|n|FactoryGirl.create(:grau,nome:n)end还有我的/factories/graus.rbFactoryGirl.definedofactory:graudonomeendend但是当我运行时:rakedb:seed我得到:rakeab

随机推荐