ABP_擴展IRepository添加自定義方法


在ABP實際使用過程有時候需要對IRepository進行擴展,增加一些自定義方法。

先創建一個自定義倉儲接口對IRepository<TEntity, TPrimaryKey>進行擴展。

using System;
using System.Linq.Expressions;
using Abp.Dependency;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;

namespace MyProject.Domain
{
    /// <summary>
    /// 定義倉儲模型中的擴展操作
    /// </summary>
    public interface IMyRepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
        where TEntity : class, IEntity<TPrimaryKey>
    {
        /// <summary>
        ///<see cref="IRepository{TEntity, TPrimaryKey}"/>擴展一個可以獲取關聯實體的FirstOrDefault操作
        /// </summary>
        /// <param name="predicate"></param>
        /// <param name="includeExpression"></param>
        /// <returns></returns>
        TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] includeExpression);
    }

    public interface IMyRepository<TEntity> : IMyRepository<TEntity, int>, IRepository, ITransientDependency
    where TEntity : class, IEntity<int>
    {
    }
}

 

創建IMyRepository的實現類MyRepository,它繼承自ABP自動創建的MyProjectRepositoryBase的這個基類。

using System;
using System.Linq;
using System.Linq.Expressions;
using Abp.Domain.Entities;
using Abp.EntityFrameworkCore;
using Abp.EntityFrameworkCore.Repositories;
using MyProject.Domain;

namespace MyProject.EntityFrameworkCore.Repositories
{
    /// <summary>
    /// 實現倉儲模型中的擴展操作
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <typeparam name="TPrimaryKey"></typeparam>
    public class MyRepository<TEntity, TPrimaryKey> :  MyProjectRepositoryBase<TEntity, TPrimaryKey>, IMyRepository<TEntity, TPrimaryKey>
        where TEntity : class, IEntity<TPrimaryKey>
    {
        public MyRepository(IDbContextProvider<MyProjectDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }

        public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] includeExpression)
        {
            return GetAllIncluding(includeExpression).FirstOrDefault(predicate);
        }
    }

    public class MyRepository<TEntity> : MyRepository<TEntity, int>, IMyRepository<TEntity>
    where TEntity : class, IEntity<int>
    {
        public MyRepository(IDbContextProvider<MyProjectDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }
    }
}

 

創建MyEfCoreAutoRepositoryTypes用於關聯倉儲接口和其默認實現。

using System;
using Abp.Domain.Repositories;
using MyProject.Domain;

namespace MyProject.EntityFrameworkCore.Repositories
{
    /// <summary>
    /// 關聯倉儲接口和其默認實現。
    /// </summary>
    public class MyEfCoreAutoRepositoryTypes
    {
        public static AutoRepositoryTypesAttribute Default { get; }

        static MyEfCoreAutoRepositoryTypes()
        {
            Default = new AutoRepositoryTypesAttribute(
                typeof(IMyRepository<>),
                typeof(IMyRepository<,>),
                typeof(MyRepository<>),
                typeof(MyRepository<,>)
            );
        }
    }
}

 

修改MyProjectEntityFrameworkModule為其添加RegisterGenericRepositoriesAndMatchDbContexes方法為DbContext中每個實體注冊一個IMyRepository的默認實現,並在Initialize中調用這個注冊方法。

using System;
using System.Reflection;
using Abp.Collections.Extensions;
using Abp.Dependency;
using Abp.EntityFramework;
using Abp.EntityFramework.Repositories;
using Abp.EntityFrameworkCore;
using Abp.EntityFrameworkCore.Configuration;
using Abp.Modules;
using Abp.Orm;
using Abp.Reflection;
using Abp.Reflection.Extensions;
using Abp.Zero.EntityFrameworkCore;
using Castle.MicroKernel.Registration;
using MyProject.EntityFrameworkCore.Repositories;
using MyProject.EntityFrameworkCore.Seed;

namespace MyProject.EntityFrameworkCore
{
    [DependsOn(
        typeof(MyProjectCoreModule), 
        typeof(AbpZeroCoreEntityFrameworkCoreModule))]
    public class MyProjectEntityFrameworkModule : AbpModule
    {
        /* Used it tests to skip dbcontext registration, in order to use in-memory database of EF Core */
        public bool SkipDbContextRegistration { get; set; }

        public bool SkipDbSeed { get; set; }

        private readonly ITypeFinder _typeFinder;

        public MyProjectEntityFrameworkModule(ITypeFinder typeFinder)
        {
            _typeFinder = typeFinder;
        }

        public override void PreInitialize()
        {
      ... } public override void Initialize() { IocManager.RegisterAssemblyByConvention(typeof(MyProjectEntityFrameworkModule).GetAssembly()); //調用注冊方法 RegisterGenericRepositoriesAndMatchDbContexes(); } public override void PostInitialize() { ... } /// <summary> /// 為DbContext中表達的實體注冊通用的Repository /// </summary> private void RegisterGenericRepositoriesAndMatchDbContexes() { //獲取所有注入的數據庫上下文 var dbContextTypes = _typeFinder.Find(type => { var typeInfo = type.GetTypeInfo(); return typeInfo.IsPublic && !typeInfo.IsAbstract && typeInfo.IsClass && typeof(AbpDbContext).IsAssignableFrom(type); }); if (dbContextTypes.IsNullOrEmpty()) { Logger.Warn("No class found derived from AbpDbContext."); return; } using (IScopedIocResolver scope = IocManager.CreateScope()) { foreach (var dbContextType in dbContextTypes) { Logger.Debug("Registering DbContext: " + dbContextType.AssemblyQualifiedName); //為數據上下文中的所有實體注冊MyEfCoreAutoRepositoryTypes的定義的Repository。 scope.Resolve<IEfGenericRepositoryRegistrar>().RegisterForDbContext(dbContextType, IocManager, MyEfCoreAutoRepositoryTypes.Default); IocManager.IocContainer.Register( Component.For<ISecondaryOrmRegistrar>() .Named(Guid.NewGuid().ToString("N")) .Instance(new EfCoreBasedSecondaryOrmRegistrar(dbContextType, scope.Resolve<IDbContextEntityFinder>())) .LifestyleTransient() ); } } } } }

 

 寫個單元測試使用IMyRepository調用自定義的FirstOrDefault對User進行查詢,並且Roles把作為關聯實體進行預加載。

    public class MyRepository_Test:MyProjectTestBase
    {
        private readonly IMyRepository<User, long> _myRepository;

        public MyRepository_Test()
        {
            //MyRepository<User, long>已經被自動注冊
            _myRepository = Resolve<IMyRepository<User, long>>();
        }

        [Fact]
        public void GetUsers_IncludeRoles_Test()
        {
            // Act
            var User = _myRepository.FirstOrDefault(t => t.Name == "admin", t => t.Roles);

            //Assert
            User.Roles.ShouldNotBeNull();
        }
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM