2017-10-12 1 views
0

J'essaie de créer un référentiel personnalisé générique à l'aide de la structure aspnetboilerplate. Je souhaite que le référentiel puisse appeler une procédure stockée dans SQL Server et renvoyer un ensemble de données à utiliser avec un type explicite.Créer un référentiel générique pour renvoyer des données à partir d'une procédure stockée avec EFCore

référentiel personnalisé:

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; 
    } 
} 

Qu'est-ce que mon service application ressemble à:

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(); 
    } 
} 

J'ai ajouté le type de retour à la DbContext comme:

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

Quand j'appelle GetTestSP, J'ai cette erreur:

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)

+0

Il existe un article sur l'exécution d'une procédure stockée avec APB. https://www.codeproject.com/Articles/1199648/Using-Stored-Procedure-User-Defined-Function-and-V –

+0

Cet article lie le référentiel à un type explicite, . J'espère garder le référentiel générique pour le typer lors de l'appel de procs stockés, en faisant correspondre le retour de la procédure avec une entité. – user1104087

Répondre

1

Ajouter [UnitOfWork] attribut et en faire une méthode virtual:

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

Vous pouvez injecter IUnitOfWorkManager pour commencer une UnitOfWork explicitement:

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(); 
    } 
} 
+0

Pas de chance avec cette approche, toujours obtenir la même erreur lorsque le contexte est affecté dans le référentiel personnalisé: Context = dbContextProvider.GetDbContext(); Pour une raison quelconque, unitOfWork est nul, donc je ne sais pas exactement comment obtenir le dbcontext. – user1104087

+0

Contrôleur. Puis-je transmettre le dbcontext du service d'application au référentiel lorsque je l'injecte? – user1104087

+0

le service d'application est injecté dans le constructeur du contrôleur. Le service d'application fonctionne bien avec d'autres méthodes. Le référentiel proc stocké est également injecté dans le constructeur du service d'application comme vu ci-dessus. – user1104087

0

Je pense que la question est votre référentiel personnalisé ne bien dbcontext. Regardez le document 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 
} 

Note: le référentiel personnalisé doit hériter EfRepositoryBase<SimpleTaskSystemDbContext, TEntity, TPrimaryKey>. Tu pourrais essayer ça.