web-dev-qa-db-ja.com

Entity Frameworkでストアドプロシージャ+リポジトリ+作業単位パターンを使用するにはどうすればよいですか?

最初にEntityFrameworkコードを使用したMVCWebアプリケーションプロジェクトがあります。このプロジェクトでは、汎用リポジトリと作業単位パターンを使用します。さらに、get listbyメソッドとget-listメソッドにストアドプロシージャを使用したいと思います。

ジェネリックリポジトリと作業単位パターンでストアドプロシージャを使用するにはどうすればよいですか?

12
sara Sodagari

汎用リポジトリに追加します

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

そして、あなたはそれを次のような任意の作業/リポジトリで呼び出すことができます

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

oW /リポジトリパターンでSPを使用しようとしないでくださいコード内で制御が難しいであり、同じエンティティタイプにマップバックしないことが多いためです。 UoWとリポジトリパターンは、エンティティフレームワークではなくADO.NETを直接使用するのに適しています。これは、EFはすでにリポジトリパターンですです。 SPを使用する場合は、より良いパターンとしてCQRSをお勧めします。 @sunilによる回答とそれに対する私のコメントを詳しく説明して、ストアドプロシージャを処理するための特別なクラスを作成しました。モックとテストも簡単です。

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);
    }
}
8
Chris Paton

汎用リポジトリの場合これを追加します:

  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();
}
1
Anas Al-Qudah

.net Core 3.1を使用している場合は、回避策を講じる必要があります

  1. ストアドプロシージャの結果を保持するクラスを作成します

  2. DBcontextから別の部分クラスを作成し、その中に前のクラスを配置します

  3. IStoredProcedureインターフェイスを作成し、ジェネリックを使用してストアドプロシージャに実装します

  4. ストアドプロシージャクラスをスタートアップクラスに挿入します

  5. 結果フォームのストアドプロシージャと同じように、結果クラスのフィールドを作成することを忘れないでください

  6. ストアドプロシージャを実行します

実装:

(1)最初のステップ

public class TaskPercents
{
    public long Id { get; set; }
    public long SchoolRepId { get; set; }

    public string Name { get; set; }
}

(2) 2番目のステップ

public partial class SchoolsPartnershipDBContext : DbContext
{
    public virtual DbSet<TaskPercents> TaskPercents { get; set; }
}

(3) 3番目のステップ

public interface IStoredProcedure<T> 
{
    public List<T> ExecuteStored(string query);
}

{
    private SchoolsPartnershipDBContext _context;

    public StoredProcedure(SchoolsPartnershipDBContext Context)
    {
        _context = Context;
    }

    public List<T> ExecuteStored(string query)
    {
        //Context = new SchoolsPartnershipDBContext();
        var r = _context.Set<T>().FromSqlRaw(query);
        return r.ToList();
        // return null;
    }
}

最後のステップ

        var result = _storedProcedure.ExecuteStored("TaskExecPercentForSchoolRep");
        return result.ToList();
0
hosam hemaily

これは私の場合はうまくいきます

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

およびunitofworkメソッド

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