2016-06-24 4 views
1

最近私はASP.NET MVC5プロジェクトで作業しています。私は、特定のビジネスルールを複製していて、コントローラ間で共有されていることに気づいたことがあります。私は何を読んでから、ASP.NET MVCのIoC/DI、UoW、およびリポジトリパターンを使用せずにコントローラアクションから「サービスレイヤー」にロジックを移動

、asp.netのMVCにおけるmは、エンティティ、のviewmodelsやサービスからなる層であり、後者のすべての共有のビジネスロジックに

を保持している今、私のように物事を維持しようとしています可能な限り単純ですが、私はエンティティフレームワークをいくつかのUoW/Repoでラップしてそのまま使用したいとは思いませんが、このアプリケーションライフタイムでエンティティフレームワークを使用するのをやめることはほとんどありません。 IoCコンテナが必要だとは思わないが、私が読んだチュートリアルでは、IoCコンテナを使うか、UoW/Repoでdbcontext/efをラップするかのようだ。

私は、httprequestごとにDbContextのインスタンス(これは私が見たチュートリアルではIoCコンテナ経由で管理されています)が1つだけあるべきであることを読んだことがあります。コントローラのコンストラクタでインスタンス化してその参照をコントローラに必要なすべてのサービスに渡してから、要求の最後に廃棄しますか?これはdbcontextを管理する正しい方法ですか?

コントローラの例:

public class SupplierController : Controller 
{ 
    private Meerkat3Context context; 
    private SupplierService supplierService; 
    private ratingService SupplierRatingService; 

    public SupplierController() 
    { 
     // instantiate the dbcontext 
     this.context = new Meerkat3Context(); 

     // pass dbcontext into the constructors of my services 
     this.supplierService = New SupplierService(context); 
     this.ratingService = New SupplierRatingService(context); 
    } 
    public ActionResult Index(Guid id) 
    { 
     var supplier = supplierService.getSupplier(id); 
     // construct viewmodel 
     return new SupplierIndexViewModel() 
     { 
      SupplierId = supplier.Id, 
      SupplierName = supplier.Name, 

      SupplierRating = ratingService.getHighestRating(supplier.Id), 
      NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id), 
      // etc 
     }; 
    } 
    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      context.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 
} 

サービス例:

public class SupplierService 
{ 
    private Meerkat3Context context; 

    public SupplierService(Meerkat3Context context) 
    { 
     this.context = context; 
    } 
    public Supplier getSupplier(Guid id) 
    { 
     return context.Where(x => x.SupplierId == id) 
         .FirstOrDefault() 
         .Select(x => new Supplier() 
         { 
          Id = x.Id, 
          Name = x.Name 
          // etc 
         }); 
    } 
    public Supplier getNearbySuppliers(Guid id) 
    { 
     return context.Suppliers.Where(x => context.SupplierAddresses 
           .Where(y => y.AddressTypeId == AddressTypes.Location) 
           .Select(z => z.Address.TownCity) 
           .Contains(x.SupplierAddresses 
              .Where(y => y.AddressTypeId == AddressTypes.Location) 
              .FirstOrDefault() 
              .Address.TownCity) 
           ); 
    } 
} 

public class SupplierRatingService 
{ 
    private Meerkat3Context context; 

    public RatingService(Meerkat3Context context) 
    { 
     this.context = context; 
    } 
    public SupplierRating getHighestRating(Guid id) 
    { 
     return context.SupplierRating 
         .Where(x => x.SupplierId == id) 
         .OrderBy(x => x.RatingValue) 
         .FirstOrDefault() 
    } 
} 
+0

これは正しいです。 –

+0

簡単にするために、VIEWModelをSQLビューと考えることができます。ここには、異なるが関連するテーブル(クラス)のさまざまなフィールドがあります。 –

答えて

1

何が欲しいのは、単にあなたのアプローチで十分です、その後、再利用可能なロジックを移動している場合。 (あなたがあなたの依存関係と

  • あなたはまだ(それは単にオブジェクト構築ロジックだ場合でも、ロジックを複製しているを隔離することはできませんテスト可能ではありません

    1. :しかし、ことを心に留めてください。例えば、あなたはあなたにもMeerkat3Contextをインスタンス化する必要がありますSupplierServiceを必要とするすべてのコントローラで)。かなり退屈得ることができること(およびDIが便利になるところだ)

  • +0

    物を処分することを忘れないように。 –

    +0

    このようにdbcontextを渡しても悪影響はありませんか?それともサービスクラスでインスタンス化する必要がありますか? – Goodsoup

    +0

    インターフェイスを実装せずにIoCコンテナを使用できます。あなたのクラスを登録し、それらのクラスを作成して廃棄するようにします。 –

    1

    あなたは取り除くしようとしている場合繰り返しコード、これはf簡単なエアリー。 VSでは、コードの一部をハイライト表示し、ホットキーCtrl+R,Ctrl+Mをリファクタリングに使用することも、コンテキストメニューhighlight code section > right-click > Refactor > Extract Methodを使用して行うこともできます。

    すべてのエンティティに対して繰り返しコードの使用を複製できる場合は、この共通機能を格納する静的クラスを作成できます。

    public sealed class Utlities 
    { 
        public static CommonA() { } 
        public static CommonB() { } 
        ... etc... 
    } 
    

    Utilities.CommonA()を使用すると簡単に呼び出すことができます。冗長性を減らす別の方法は、ViewModelsを使用することです。基本的には、Viewに必要な追加のプロパティを持つViewModelとして使用するエンティティのコピーを作成します。モデルに共通のデータがある場合は、それらの共通点を継承する基本クラスを作成します。

    public class BaseViewModel 
    { 
        public Type Prop {get; set;} 
        public Type Prop2 {get; set;} 
        ...etc... 
    } 
    
    public class SpecificViewModel : BaseViewModel 
    { 
        SpecificViewModel(Type Prop, Type Prop2) : base(Prop, Prop2, ...etc...) { } 
        public Type specificProp {get; set;} 
        ...etc... 
    } 
    

    私はあなたの質問を正しく理解しています。

    1

    IoCコンテナを使用すると、コントローラは次のようになります。

    public class SupplierController : Controller 
        { 
         //the controller doesn't need to create the db context now 
         //this concern is handled now by the IoC container 
    
         private SupplierService supplierService; 
         private RatingService SupplierRatingService; 
    
         public SupplierController(SupplierService supplierService, RatingService ratingService) 
         { 
          // we don't have to pass the db context now to services, since we retrieve the services from the IoC container. The IoC container auto-wires the services 
          this.supplierService = supplierService; 
          this.ratingService = ratingService; 
         } 
         public ActionResult Index(Guid id) 
         { 
          var supplier = supplierService.getSupplier(id); 
          // construct viewmodel 
          return new SupplierIndexViewModel() 
          { 
           SupplierId = supplier.Id, 
           SupplierName = supplier.Name, 
    
           SupplierRating = ratingService.getHighestRating(supplier.Id), 
           NearbySuppliers = supplierService.getNearbySuppliers(supplier.Id), 
           // etc 
          }; 
         } 
         // the controller doesn't need a dispose method since the IoC container will dispose the dbcontext for us 
        } 
    

    あなたはIoCコンテナを使用する依存関係逆転の原則に従う必要はありませんが、作成すると、あなたのサービスオブジェクトの寿命を管理するために、IoCコンテナに数えることができます。

    Webリクエストごとに1つのdbcontextインスタンスを作成するようにIoCコンテナを設定します。これは設定可能です。サービスごとに異なるdbcontextインスタンスを後で作成する方が良いと判断した場合は、新しいキーワードを使用するすべてのコントローラやアクションメソッドではなく、単一の場所でこれを変更してください。

    関連する問題