使用ABP框架踩过的坑系列5

匿名 (未验证) 提交于 2019-12-02 22:10:10

 public static class DbContextConfigurer     {         public static void Configure(DbContextOptionsBuilder<DbContext> builder, string connectionString)         {             //builder.UseSqlServer(connectionString); //使用MSSQL             builder                 //.UseLoggerFactory(MyLoggerFactory)                 .UseMySql(connectionString);  //使用MySql         }          public static void Configure(DbContextOptionsBuilder<DbContext> builder, DbConnection connection)         {             //builder.UseSqlServer(connection);             builder.UseMySql(connection);         }     }

用ABP模板生成的项目中,如果使用.netcore和EFcore, 就会有DbContextConfigurer,只要安装了Microsoft.entityframeworkcore.mysql, 就可以使用UseMySql这个扩展方法,

 "ConnectionStrings": {     //"Default": "Server=localhost; Database=Db3; Trusted_Connection=True;"     "Default": "Server=localhost;port=3306;database=Db3;uid=root;password=root;character set=utf8;Old Guids=true"   },

appsettings.json 里ConnectionStrings,也使用Mysql连接字符串,然后再PMC(程序包控制台)执行

update-dabase

然后再PMC(程序包控制台)执行

install-package Pomelo.EntityFrameworkCore.MySql

再执行update-dabase, 真的一切都好了,其实在ORM的抽象和实现方面,ABP都比较好的Module, 当家的是Microsoft的EF

Abp.EntityFrameWork.Common   //EF的公共部分 Abp.EntityFrameWork  //EF Abp.EntityFrameWorkCore //EFCore

还有来自Java阵营的

Abp.NHibernate

还有几个比较流行的,

Abp.Dapper //据说性能是ef几十倍的DapperAbp.MongoDB //nosql,KV和文档数据库Abp.MemoryDb //内存数据库,可用于单元测试,棒棒的

个人还是偏爱EF系列,特别是linux下用EFCore+Mysql, 是最佳组合,经过几个项目的实战,证明是个不错选择,可以放心使用!

ABP有关ORM的抽象机制,主要通过Repostitory和UnitOfWork来做的

namespace Abp.Domain.Repositories {     /// <summary>     /// This interface is implemented by all repositories to ensure implementation of fixed methods. 说白了就是CRUD得封装     /// </summary>     /// <typeparam name="TEntity">Main Entity type this repository works on</typeparam>     /// <typeparam name="TPrimaryKey">Primary key type of the entity</typeparam>     public interface IRepository<TEntity, TPrimaryKey> : IRepository where TEntity : class, IEntity<TPrimaryKey>     {         #region Select/Get/Query        ...#endregion          #region Insert        ...#endregion          #region Update        ...#endregion          #region Delete        ...#endregion          #region Aggregates         ...#endregion     } }
/// <summary>     /// Defines a unit of work.     /// This interface is internally used by ABP. 实际上就是数据库连接和事务的封装     /// Use <see cref="IUnitOfWorkManager.Begin()"/> to start a new unit of work.     /// </summary>     public interface IUnitOfWork : IActiveUnitOfWork, IUnitOfWorkCompleteHandle     {         /// <summary>         /// Unique id of this UOW.         /// </summary>         string Id { get; }          /// <summary>         /// Reference to the outer UOW if exists.         /// </summary>         IUnitOfWork Outer { get; set; }                  /// <summary>         /// Begins the unit of work with given options.         /// </summary>         /// <param name="options">Unit of work options</param>         void Begin(UnitOfWorkOptions options);

具体我们在Service中,只要用DI就可以注入了,其实现机理,以EFCore为例

/// <summary>     /// This module is used to implement "Data Access Layer" in EntityFramework. 类似Mybatis的数据访问层,在ABP中叫基础架构     /// </summary>     [DependsOn(typeof(AbpKernelModule))]     public class AbpEntityFrameworkCoreModule : AbpModule     {         。。。private void RegisterGenericRepositoriesAndMatchDbContexes()         {             var dbContextTypes =                 _typeFinder.Find(type =>                     type.IsPublic &&                     !type.IsAbstract &&                     type.IsClass &&                     typeof(AbpDbContext).IsAssignableFrom(type)                     );              if (dbContextTypes.IsNullOrEmpty())             {                 Logger.Warn("No class found derived from AbpDbContext.");                 return;             }              using (var repositoryRegistrar = IocManager.ResolveAsDisposable<IEfCoreGenericRepositoryRegistrar>())             {                 foreach (var dbContextType in dbContextTypes)                 {                     Logger.Debug("Registering DbContext: " + dbContextType.AssemblyQualifiedName);                     repositoryRegistrar.Object.RegisterForDbContext(dbContextType, IocManager);                 }             }             。。。         }     }
 public class EfCoreGenericRepositoryRegistrar : IEfCoreGenericRepositoryRegistrar, ITransientDependency     {        。。。public void RegisterForDbContext(Type dbContextType, IIocManager iocManager)         {             var autoRepositoryAttr = dbContextType.GetSingleAttributeOrNull<AutoRepositoryTypesAttribute>() ??                                      EfCoreAutoRepositoryTypes.Default;              foreach (var entityTypeInfo in DbContextHelper.GetEntityTypeInfos(dbContextType))             {                 var primaryKeyType = EntityHelper.GetPrimaryKeyType(entityTypeInfo.EntityType);                 if (primaryKeyType == typeof(int))                 {                     var genericRepositoryType = autoRepositoryAttr.RepositoryInterface.MakeGenericType(entityTypeInfo.EntityType);                     if (!iocManager.IsRegistered(genericRepositoryType))                     {                         var implType = autoRepositoryAttr.RepositoryImplementation.GetGenericArguments().Length == 1                                 ? autoRepositoryAttr.RepositoryImplementation.MakeGenericType(entityTypeInfo.EntityType)                                 : autoRepositoryAttr.RepositoryImplementation.MakeGenericType(entityTypeInfo.DeclaringType, entityTypeInfo.EntityType);                          iocManager.Register(                             genericRepositoryType,                             implType,                             DependencyLifeStyle.Transient                             );                     }                 }                  var genericRepositoryTypeWithPrimaryKey = autoRepositoryAttr.RepositoryInterfaceWithPrimaryKey.MakeGenericType(entityTypeInfo.EntityType, primaryKeyType);                 if (!iocManager.IsRegistered(genericRepositoryTypeWithPrimaryKey))                 {                     var implType = autoRepositoryAttr.RepositoryImplementationWithPrimaryKey.GetGenericArguments().Length == 2                                 ? autoRepositoryAttr.RepositoryImplementationWithPrimaryKey.MakeGenericType(entityTypeInfo.EntityType, primaryKeyType)                                 : autoRepositoryAttr.RepositoryImplementationWithPrimaryKey.MakeGenericType(entityTypeInfo.DeclaringType, entityTypeInfo.EntityType, primaryKeyType);                      iocManager.Register(                         genericRepositoryTypeWithPrimaryKey,                         implType,                         DependencyLifeStyle.Transient                         );                 }             }         }     }

整个目的就是为了可以注入泛型的IRepostitory<TEntity, TPrimaryKey>,我们的service,就可以愉快的使用了

public IRepository<FoodMaterial, long> FoodMaterialRepository { get; set; } //属性注入 //或 private IRepository<FoodMaterialCategory, long> _categoryRepository;         public FoodMaterialAppService(IRepository<FoodMaterial, long> repository                                     , IRepository<FoodMaterialCategory, long> categoryRepository)              : base(repository)         {             _categoryRepository = categoryRepository;         } // 构造注入

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!