Как я могу использовать хранимую процедуру + репозиторий + блок шаблонов работы в Entity Framework?

Сначала у меня есть проект веб-приложения MVC с кодом Entity Framework. В этом проекте я собираюсь использовать общий репозиторий и единицу рабочих шаблонов. Кроме того, я хочу использовать хранимые процедуры для получения списка с помощью методов get-list.

Как я могу использовать хранимые процедуры с общим хранилищем и единицей рабочих шаблонов?

Ответ 1

В общий репозиторий добавить

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

И затем вы можете вызвать его с помощью любого unitofwork/репозитория, например

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

Ответ 2

Разрабатывая ответ @sunil и мой комментарий к нему, я создал класс специально для обработки хранимых процедур. Как я уже упоминал в своем комментарии, если вы ожидаете от модели другой модели, отличной от той, что указана в вашем репозитории, у вас есть проблемы. Кроме того, если вы хотите только выполнить SP, то вы нарушаете ISP. Ниже мое решение. Это отнюдь не является окончательным и может быть легко расширено или изменено в соответствии с вашими потребностями.

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

Ответ 3

Для общего репозитория Добавьте это:

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

И вам просто нужно отправить имя хранимой процедуры и массив параметров:

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

Ответ 4

это работает в моем случае

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

и метод единицы работы

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