wake-up-neo.com

Wie kann ich eine gespeicherte Prozedur + ein Repository + eine Einheit von Arbeitsmustern in Entity Framework verwenden?

Ich habe zuerst ein MVC-Webanwendungsprojekt mit Entity Framework-Code. In diesem Projekt verwende ich ein generisches Repository und Arbeitseinheitenmuster. Außerdem möchte ich gespeicherte Prozeduren zum Abrufen der Methoden list by und get-list verwenden.

Wie kann ich gespeicherte Prozeduren mit generischem Repository und Arbeitseinheitenmustern verwenden?

12
sara Sodagari

Zu Ihrem generischen Repository hinzufügen

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

Und dann können Sie es mit jeder Unit of Work/Repository wie aufrufen

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

Sie sollten nicht versuchen, SPs mit UoW/Repository-Muster zu verwenden , da sie schwer zu steuern im Code sind und häufig nicht demselben Entitätstyp zugeordnet werden. UoW- und Repository-Muster eignen sich besser für die direkte Verwendung von ADO.NET und nicht von Entity Framework, da EF bereits ein Repository-Muster ist . Ich würde CQRS als besseres Muster bei der Verwendung von SPs vorschlagen. Ich habe auf die Antwort von @sunil und meinen Kommentar dazu eingegangen und eine Klasse speziell für den Umgang mit gespeicherten Prozeduren erstellt. Es ist auch leicht zu verspotten und zu testen.

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

Für das generische Repository fügen Sie Folgendes hinzu:

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

Und Sie müssen nur den Namen der gespeicherten Prozedur und das Array der Parameter senden:

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

das funktioniert in meinem fall

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

und die unitofwork Methode

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