使用 EFCore 创建用于从存储过程返回数据的通用存储库

Create generic repository for returning data from stored procedure with EFCore

我正在尝试使用 aspnetboilerplate 框架创建一个通用的自定义存储库。我希望存储库能够调用 SQL 服务器中的存储过程和 return 一组用于显式类型的数据。

自定义存储库:

public class PMStoredProcedureRepository<T> : IPMStoredProcedureRepository<T> where T : class
{
    private MyDbContext Context { get; set; }

    public PMStoredProcedureRepository(IDbContextProvider<MyDbContext> dbContextProvider)
    {
        Context = dbContextProvider.GetDbContext();
    }

    // When you expect a model back (async)
    public IQueryable<T> ExecuteSP(string query, params object[] parameters)
    {
        var type = Context.Set<T>().FromSql(query, parameters);
        return type;
    }
}

我的应用服务是什么样的:

public class DashboardAppService : MyAppServiceBase, IDashboardAppService
{
    // Entity repositories
    private readonly IPMStoredProcedureRepository<PMTestSP> _storedProcRepository;

    public DashboardAppService(
        IPMStoredProcedureRepository<PMTestSP> storedProcRepository
        )
    {
        _storedProcRepository = storedProcRepository;
    }

    public List<PMTestSP> GetTestSP()
    {
        var ret = _storedProcRepository.ExecuteSP("exec pme_TestProcedure", new SqlParameter("inputString", "abcde"));
        return ret.ToList();
    }
}

我将 return 类型添加到 DbContext 中:

public virtual DbSet<PMTestSP> PMTestSP { get; set; }

当我调用 GetTestSP 时,出现此错误:

ArgumentNullException: Value cannot be null. Parameter name: unitOfWork Abp.EntityFrameworkCore.Uow.UnitOfWorkExtensions.GetDbContext(IActiveUnitOfWork unitOfWork, Nullable multiTenancySide) Abp.EntityFrameworkCore.Uow.UnitOfWorkDbContextProvider.GetDbContext(Nullable multiTenancySide) Abp.EntityFrameworkCore.Uow.UnitOfWorkDbContextProvider.GetDbContext() Company.Name.EntityFrameworkCore.Repositories.PMStoredProcedureRepository..ctor(IDbContextProvider dbContextProvider) in PMStoredProcedureRepository.cs + Context = dbContextProvider.GetDbContext(); Castle.Proxies.PMStoredProcedureRepository`1Proxy..ctor(IInterceptor[] , IDbContextProvider )

添加 [UnitOfWork] 属性并使其成为 virtual 方法:

[UnitOfWork]
public virtual List<PMTestSP> GetTestSP()
{
    // ...
}

您可以注入 IUnitOfWorkManager 以显式开始 UnitOfWork

public List<PMTestType> GetTestSP()
{
    using (var uow = UnitOfWorkManager.Begin())
    {
        var ret = _storedProcRepository.ExecuteSP("exec pme_TestProcedure", new SqlParameter("inputString", "abcde"));
        uow.Complete();
        return ret.ToList();
    }
}

我认为问题是您的自定义存储库没有获得正确的 dbcontext。查看文档Create custom repository

public class SimpleTaskSystemRepositoryBase<TEntity, TPrimaryKey> : EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>
    where TEntity : class, IEntity<TPrimaryKey>
{
    public SimpleTaskSystemRepositoryBase(IDbContextProvider<SimpleTaskSystemDbContext> dbContextProvider)
        : base(dbContextProvider)
    {
    }

    //add common methods for all repositories
}

注意:自定义存储库必须继承EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>。你可以试试这个。