2016-11-02 1 views
1

私のasp.net mvcエンティティフレームワーク6プロジェクトで単体テストを行いたいので、自分のコードを見せなくてはなりません。私は自分のコントローラを自分の状況にさらして、おそらくそれを分けておくべきだと決めました。私は最初にリポジトリ/ UoWパターンを見ていましたが、多くを読んだ後、DIを使って単純なサービスパターンを決定しました(コントローラにはGetProducts()FindProduct()などのサービスが注入されています)。サービスパターンエンティティフレームワークasp.net mvc

私の質問はこのパターンでの変更の追跡に関するものです。多くのことは、コントローラ方式で行われますが、これらのようにすべて作られたメソッドを分離した後、私はちょうどSaveChanges()を呼び出します前に:あなたはSaveChanges()が2回呼び出されていることがわかり上記で

public void AddRequest(Request request) 
    { 
     using (PricedNotesContext ctxt = new PricedNotesContext()) 
     { 
      ctxt.Requests.Add(request); 
      ctxt.SaveChanges(); 
     } 
    } 

public void DeleteRequestData(BaseRequestData reqData) 
    { 
     using (PricedNotesContext ctxt = new PricedNotesContext()) 
     { 
      ctxt.RequestData.Remove(reqData); 
      ctxt.SaveChanges(); 

     } 
    } 

を。しかし、私はそれが一度呼び出されるだけです。両方の操作が正常に完了した場合、私の変更だけが持続するようにしたい。お勧めの解決方法は、SaveChanges()Dispose()というメソッドを持っているだけで、明らかにトランザクションを管理するコントローラにはSaveChanges()Dispose()が公開されていますか?

ありがとうございました!

+2

作業単位について読むことをお勧めします。データレイヤーコンポーネントではなく、アプリケーション/ビジネスレイヤー内の作業単位/コンテキストを一度だけインスタンス化します。そして、それをさらに注入してください。 –

+2

ええ。 PriceNotesContextをすべてのメソッドでインスタンス化するのではなく、コントローラに注入する必要があります。 Web環境では、コンテキスト自体が作業単位のように動作するため、実際に作業単位は必要ありません。私はBeginRequestでTransactionScopeを作成し、EndRequestでコミットします。今あなたの操作のどれもアトミックではありません。 – Fran

+0

これは本質的に私が今持っているものです。私は私のサービスメソッドでSaveChanges()を使用していますが、トランザクション制御を行っています。 (質問のメソッドはサービスであり、以前のコントローラではありません。 – coolboyjules

答えて

2

サービスでは、コンシューマがコンテキストの保存に気を付けなくて済むような機能を提供する必要があります。実際には、文脈についてはわかりません。なぜあなたは、単にような何かはありません。

public class EfNotesService : INotesService 
{ 
     public ExecuteSomeBusinessOperation(input parameters here) 
     { 
      // Validate input parameters 

      using (PricedNotesContext ctxt = new PricedNotesContext()) 
      { 
       ctxt.Requests.Add(...); 
       ctxt.RequestData.Remove(...); 

       // other logic 

       ctxt.SaveChanges(); 
      } 
     } 
} 

あるいはさらに良いと、あなたはまた、要求の開始時にコンテキストを注入し、リクエストの終了時に、それを処分する依存性注入を使用することができます。このコンテキストは、その後EfNotesServiceのコンストラクタに注入され、そしてあなたはちょうどusingステートメントせずに使用することができます。このよう

public class EfNotesService : INotesService 
{ 
     private readonly PricedNotesContext _ctxt; 

     public EfNotesService(PricedNotesContext ctxt) 
     { 
      _ctxt = ctxt; 
     } 
     public ExecuteSomeBusinessOperation(input parameters here) 
     { 
      // Validate input parameters 

      _ctxt .Requests.Add(...); 
      _ctxt .RequestData.Remove(...); 

      // other logic 

      _ctxt .SaveChanges();    
     } 
} 

、同じ文脈では、複数のサービスにまたがることができ、あなたが心配する必要はありませんこれらのサービスにコンテキストを作成して廃棄する。

さらに、サービス操作では、サービスのすべてを行うのではなく、ビジネスロジックを実行するためにビジネスコンポーネントまたはドメインレイヤーを使用することもできます。

グローバル例外ハンドラを追加して、例外を正常に処理します。

+0

はいいいえ。ありがとう。これは私が持っていたものに非常に近いです。私は現在、あなたの例のようにサービス内にコンテキストを挿入するためにDIを使用しています。私はSaveChanges()を公開せず、ビジネス操作ですべてを処理します。 – coolboyjules

+0

そして、このロジックを1つのサービス操作で処理するのに間違っていることはありません。このように、単純なCRUD操作ではなく、実際に操作の目的を公開しています。 –

+0

はい、間違いでした。私は私のサービスでビジネスの代わりにCRUDをやっていました。 – coolboyjules

1

ここで私が思いついたのです。

public class EfNotesService : INotesService 
{ 
    private readonly PricedNotesContext _ctxt = new PricedNotesContext(); 

    public IEnumerable<Request> GetAllRequests() 
    { 
     return _ctxt.Requests.ToList(); 
    } 

    public void SaveRequest(Request request) 
    { 
     _ctxt.Entry(request).State = EntityState.Modified; 
    } 

    public void DeleteRequestData(BaseRequestData reqData) 
    { 
     _ctxt.RequestData.Remove(reqData); 
    } 
    // ... 
    // Other methods... 
    // ... 

    // Transaction control 
    public void SaveChanges() 
    { 
     _ctxt.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     _ctxt.Dispose(); 
    } 
} 

これはUoWやリポジトリではありませんが、単純であり、うまく機能します。さらに、私はDbContextのすべての「ストア」のメリットを維持します。

+0

あなたのサービスでは「取引管理」ではありません。そのためにはTransactionScopeを使用する必要があります。 TransactionScopeのスコープを設定する必要があります。これは、すべてのサービス呼び出しを同じトランザクションでラップするためです。 – Fran

+0

このサービスのコンシューマが実際にSaveChanges()を呼び出す必要があるのはちょっと変わっていませんか?私の意見では、このデータロジックを抽象化する必要があります。消費者は必要なメソッドを呼び出すだけで、Saveメソッドを呼び出すことに気を付ける必要はありません。 –

+0

それは公正です。 OK私は別のものを調べます。 – coolboyjules