web-dev-qa-db-fra.com

Comment utiliser une procédure stockée + un référentiel + des modèles d'unités de travail dans Entity Framework?

J'ai d'abord un projet d'application Web MVC avec le code Entity Framework. Dans ce projet, je vais utiliser des modèles génériques de référentiel et d'unités de travail. De plus, je souhaite utiliser des procédures stockées pour les méthodes get list by et get-list.

Comment utiliser des procédures stockées avec des modèles génériques de référentiel et d'unité de travail?

12
sara Sodagari

Ajoutez à votre référentiel générique

public IEnumerable<T> ExecWithStoreProcedure(string query, params object[] parameters)
{
        return _context.Database.SqlQuery<T>(query, parameters);
}

Et puis, vous pouvez l’appeler avec n’importe quel unitofwork/référentiel comme

IEnumerable<Products> products = 
             _unitOfWork.ProductRepository.ExecWithStoreProcedure(
             "spGetProducts @bigCategoryId",
             new SqlParameter("bigCategoryId", SqlDbType.BigInt) { Value = categoryId } 
      );
21
sunil

Vous ne devriez pas essayer d'utiliser les SP avec UoW/Repository pattern , car ils sont difficiles à contrôler dans le code et ne correspondent souvent pas au même type d'entité. UoW et le modèle de référentiel conviennent mieux à l’utilisation directe d’ADO.NET et non d’Entity Framework, car EF est déjà un modèle de référentiel . Je suggérerais CQRS comme meilleur modèle lors de l'utilisation de SP. En développant la réponse de @sunil et mon commentaire à ce sujet, j'ai créé une classe spécialement pour la gestion des procédures stockées. Il est facile de se moquer et de tester, aussi.

public class ProcedureManager : IProcedureManager
{
    internal DbContext Context;

    public ProcedureManager(DbContext context)
    {
        Context = context;
    }

    //When you expect a model back (async)
    public async Task<IList<T>> ExecWithStoreProcedureAsync<T>(string query, params object[] parameters)
    {
        return await Context.Database.SqlQuery<T>(query, parameters).ToListAsync();
    }

    //When you expect a model back
    public IEnumerable<T> ExecWithStoreProcedure<T>(string query)
    {
        return Context.Database.SqlQuery<T>(query);
    }

    // Fire and forget (async)
    public async Task ExecuteWithStoreProcedureAsync(string query, params object[] parameters)
    {
        await Context.Database.ExecuteSqlCommandAsync(query, parameters);
    }

    // Fire and forget
    public void ExecuteWithStoreProcedure(string query, params object[] parameters)
    {
        Context.Database.ExecuteSqlCommand(query, parameters);
    }
}
7
Chris Paton

Pour le référentiel générique Ajouter ceci:

  public IEnumerable<TEntity> GetdataFromSqlcommand(string command, System.Data.SqlClient.SqlParameter[] parameter)
    {
        StringBuilder strBuilder = new StringBuilder();
        strBuilder.Append($"EXECUTE {command}");
        strBuilder.Append(string.Join(",", parameter.ToList().Select(s => $" @{s.ParameterName}")));

        return Context.Set<TEntity>().FromSql(strBuilder.ToString(), parameter);
    }

Et il vous suffit d’envoyer le nom de la procédure stockée et le tableau de paramètres:

public IEnumerable<MainData> GetMainData(Param query)
{
    var param1 = new SqlParameter("param1", query.param1);
    var param2 = new SqlParameter("param2", query.param2);
    return GetdataFromSqlcommand("StoredProcedurename", parameter: new[] { param1, param2 }).ToList();
}
1
Anas Al-Qudah

cela fonctionne dans mon cas

    IQueryable<Cm_Customer> customerQuery = _uow.SqlQuery<Cm_Customer>(@" DECLARE @UserId INT = {0}
                                               EXEC Cm_GetCustomersByUserId @UserId", filter.UserId).AsQueryable();

et la méthode unitofwork

public IEnumerable<TEntity> SqlQuery<TEntity>(string sql, params object[] parms)
{
    return _context.Database.SqlQuery<TEntity>(sql, parms);
}
0
dewelloper