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