私は、GenericRepoパターンとEF6データベースを最初に使用する既存のアプリケーションに取り組んでいます。エンティティモデルの既存のエンティティではない複合型を返すストアドプロシージャを呼び出しているため、どの型を指定すればよいかわかりません。
これは私のspが私のサービスレイヤーから呼び出される方法です
_unitOfWork.Repository<Model>()
.SqlQuery("sp_Get @FromDateTime, @ToDateTime, @CountyId",
new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime },
new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime },
new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) }
).ToList();
データレイヤーにエンティティを作成してマップしますか、それとも複雑な型を返すストアドプロシージャに最適なアプローチは何ですか。もしそうなら、カスタムマッピングが必要ですか、それともエンティティクラスを作成する場合だけですか
ありがとうございました
これらのフィールドを持つエンティティがある場合は、上記のようにSqlQueryメソッドを呼び出すことができます。そうでない場合は、結果をマップするための新しいクラスを作成することをお勧めします。
public class Result
{
public int CountyId { get; set; }
public DateTime FromDateTime { get; set; }
public DateTime ToDateTime { get; set; }
}
あなたのケースでUnitOfWorkパターンがどのように実装されているかはわかりませんが、コンテキストにアクセスできると思います。 UnitOfWork
クラスでは、次のようなジェネリックメソッドを作成できます。
public class UnitOfWork
{
private YourContext Context { get; set; }
public DbRawSqlQuery<T> SQLQuery<T>(string sql, params object[] parameters)
{
return Context.Database.SqlQuery<T>(sql, parameters);
}
}
このようにして、以下に示すようにストアドプロシージャを実行できます。
var result= _unitOfWork.SqlQuery<Result>("sp_Get @FromDateTime, @ToDateTime, @CountyId",
new SqlParameter("FromDateTime", SqlDbType.DateTime) { Value = Request.FromDateTime },
new SqlParameter("ToDateTime", SqlDbType.DateTime) { Value = Request.TripToDateTime },
new SqlParameter("CountyId", SqlDbType.Int) { Value = Convert.ToInt32(Request.County) }
).ToList();
リポジトリパターン の目的は、データの保存と取得を抽象化して、クライアントコードを保護することです。データがどのように永続化されるかについて何も知る必要がないビジネス層(あなたの場合はサービス層)。たとえば、SQLステートメントはリポジトリクラス内にのみ存在し、コード全体に波及することはありません。
SQL、ストアドプロシージャの名前、およびパラメータをクライアントコードに公開すると、リポジトリパターンのメリットはあまり得られず、実際にはリポジトリとはまったく呼ばれません。データアクセス層とは独立して、リポジトリをモックし、ビジネス層をテストできるという利点が失われます。つまり、ビジネスロジックを検証するには、統合テスト(完全なデータベースインスタンスが必要)が必要です。
国エンティティなどを返すGetCountry(int CountryId、DateTime fromDate、DateTime toDate)メソッドを持つCountryRepositoryクラスを持つようにリファクタリングを検討してください。あなたのコードの可読性があなたの質問のコードと比較してはるかに改善されることにあなたは同意すると思います。
public class CountryRepository
{
public Country GetCountry(int CountryId, DateTime fromDate, DateTime toDate)
{
// EF or ADO.NET code here
}
}
その場合、クライアントコードは次のようになります。
var c = unitOfWork.CountryRepository.GetCountry(1, DateTime.Now.AddYears(-1), DateTime.Now);
こちらもご覧ください SO質問
IQueryable<Cm_Customer> customerQuery = _uow.SqlQuery<Cm_Customer>(@" DECLARE @UserId INT = {0}
EXEC Cm_GetCustomersByUserId @UserId", filter.UserId).AsQueryable();
IQueryable<Cm_Customer> custs = customerQuery.IncludeMultiple(k => k.Cm_CustomerLocations,
k => k.Cm_CustomerSalesmans,
k => k.Cm_CustomerMachineparks,
k => k.Cm_CustomerAuthenticators,
k => k.Cm_CustomerInterviews,
k => k.Cm_CustomerRequest,
k => k.Cm_MachineparkRental).AsQueryable();
public virtual IEnumerable<T> GetWithRawSql(string query, params object[] parameters)
{
return DbSet.SqlQuery(query, parameters).ToList();
}
インターフェース
IEnumerable<T> GetWithRawSql(string query, params object[] parameters);