私はEntity Framework(EF)をORMとしてSQL Serverにリンクする新しいプロジェクトを開始しようとしています。私は、抽象概念に関してEFを扱うための良いアプローチが何であり、最終的に私のコードをテスト可能にするかを理解するために、大量の読書をしてきました。エンティティフレームワークよりも優れたリポジトリ抽象化を使用していますか?
問題は読むほどですが、私はもっと混乱しています。私はすべてそれになります。
私はロットから、彼らはインターフェースやテスト目的でモックやすい経由して簡単に、注射されているので、それらを作る、リポジトリのルートを下るつもりだった:私は行くには良い方法だと思った何
私が見つけたと思われる例のうち、このアプローチで誓いを立てる人がたくさんいます。 EFと対話するリポジトリパーツについては、Reposにビジネスロジックがないため、統合テストを行うつもりだったので、それを処理するService/Controllerクラスに移行しました。
一部は、リポジトリパターンは、他のリンクがあった不当な抽象
http://ayende.com/blog/3955/repository-is-the-new-singleton
ですが、私は、私は一種の取得あまりにも多くの
でこの質問を氾濫したくなかったと言いますこれは、私はEFとそれの実装は本質的に抽象ですが、私には具体的なもの(それはアプリケーションの範囲外に何かを打つ... DB)私の問題はpです私はおそらく私のサービス内からデータコンテキストと作業単位のデータとやりとりすることになるでしょうが、データアクセスログインとそのレベルのビジネスロジックを混在させているような感じです。それから私はユニットテストをどうやって行うのですか?
私は今、明確な方向性がなく、避けられないコーダーブロックが設定されているようです。私はきれいで、私はテストすることができるアプローチを探しています。
UPDATE - 私は
を始めるつもりですソリューション私はサイモンによって与えられた答えの1、その後わずかに異なるパスを行ってきましたが、私は読んでいたが、彼は私ので、再投稿記事のおかげで再びそれを乗り越えた。まず、私は既存のデータベースを持っていて、何らかの理由でデザイナーツールが気に入らないので、Code Firstを使用しています。私はいくつかのシンプルなPOCOオブジェクトといくつかのマッピングを作成しました。ここでは単純にしていますが、私はちょうど1つのPOCO/Mappingを表示します。
POCO
public abstract class BaseEntity<T>
{
[Key]
public T Id { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
}
public class Project : BaseEntity<int>
{
public virtual ICollection<Site> Sites { get; set; }
public bool Active { get; set; }
}
作業インターフェースの単位
public interface IUnitOfWork
{
IDbSet<Project> Projects { get; }
void Commit();
}
コンテキスト
internal class MyContext : DbContext
{
public MyContext(string connectionString)
: base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ProjectMap());
}
}
コンクリートのUnitOfWork
public class UnitOfWork : IUnitOfWork
{
readonly MyContext _context;
const string ConnectionStringName = "DBConn";
public UnitOfWork()
{
var connectionString = ConfigurationManager.ConnectionStrings[ConnectionStringName].ConnectionString;
_context = new FosilContext(connectionString);
}
public IDbSet<Project> Projects
{
get { return _context.Set<Project>(); }
}
public void Commit()
{
_context.SaveChanges();
}
}
基本的なテストコード
var _repo = new UnitOfWork().Projects;
var projects = from p in _repo
select p;
foreach (var project in projects)
{
Console.WriteLine(string.Format("{0} - {1} - {2} - {3})", project.Id, project.Name, project.Active.ToString(), project.CreatedOn.ToShortDateString()));
}
Console.Read();
たUnitOfWorkは自明であるが、具体的な状況に基づいて、私は偽IUnitOfWorkを作成し、テストのために偽IDBSetに渡し。私にとっては、これは構造的に私を噛ませるために戻ってくるかもしれませんが、私はこれに入り込みますが、この抽象的なEFの上にRepoはありません。記事ではIDbSetはRepoと同等なので、私が使っていることを説明しています。私はUoWの背後に私のカスタム・コンテキストを隠しているんだけど、どうやってそれがどうやって見えるのか見ていきます。
私は今、データやビジネスルールの検索をカプセル化するサービスレイヤーでこれを使用できますが、EF固有のアイテムを偽装することができるようにユニットテスト可能でなければならないと考えています。うまくいけば、それは私のコントローラがかなりリーンになりますが、私たちは:)
Entity Frameworkを使用している場合は、UnitOfWorkに似た 'DbContext'とリポジトリに似た' DbSet'があることを忘れないでください。この質問は個人的な意見を招き、Stack Overflowには適していないかもしれませんが、Entity Frameworkを使用する場合は、パターンを受け入れる可能性があります。 'DbContext'と' DbSet'sをさらにラッピングすることは、実際には、単体テストの容易さとある程度の依存性注入のために、コンクリートクラスに対して非常に薄い抽象化を与えることです。 –
コメントありがとうございます。私が得意でないもの(私はEFにとって非常に新しい)は、この薄い層がどのように見えるかです。私は具体的にEFについてのビデオを見ていて、作者はIDetetを使ってIContextインターフェースを導入しましたが、別の作業単位(これらの例はリポジトリを使用しました)が渡されました。薄い層はIDBSetとIContextでした。作者は、リポジトリパターンの問題とまったく同じように見える抽象概念を使ってEFを隠していると指摘しましたか? – Modika
私はテキストの壁を以前の答えに戻しています。文字の制限により、書式設定が少し難しくなります。 –