web-dev-qa-db-ja.com

依存関係はMVCコントローラーにDbContextを挿入します

Entity FrameworkのDbContextをMVCコントローラーに挿入することについて懸念があります。

以下は私のコードのサンプルです。これを設計した方法は、実際のまたは模擬のDbContextを挿入することにより、コントローラーコードの単体テストをより適切に行えるようにするためです。

私が現在計画しているのは、UnityとIDbEntitiesインターフェイスを使用して、DbContextをコントローラーに挿入することです。このコントローラーから新しいアクションが呼び出されるたびに、Unityはコントローラーコンストラクターを呼び出し、IDbEntitiesインターフェイスを実装する新しいDbContextオブジェクトを作成します。そうすれば、新しいリクエストごとに新鮮なコンテキストオブジェクトができます。これはかなり安全だと思います。

私の懸念は次に何が起こるかです。アクションでは、同じDbContextオブジェクトを使用して、同じまたは異なるデータサービスを複数回呼び出すことができます。たとえば、私のIndex()アクションでは、UpdateEvent(dbContext)を呼び出してから、同じDbContextオブジェクトを使用してSoftDeleteEvent(dbContext)を呼び出すか、同じコンテキストを別のデータサービスに渡すこともできます。たとえば、UserService.LogoutUser(dbContext )。

同じDbContextオブジェクトのすべての受け渡しが安全かどうかはわかりません。

このようにDbContextを渡しても安全ですか、それともユニットテストの目的でDataServiceからコントローラーにDbContextを抽出するより良い方法がありますか?

コントローラ:

public class EventsController : Controller
{    
    private IDbEntities _dbContext;

    public EventsController(IDbEntities entities)
    {
        _dbContext = entities;
    }

    public ActionResult Index()
    {
        // Hypothetical operations. In reality update and delete of the same record rarely happen in the same code branch
        var events = _eventService.AllEvents(_dbContext);
        _eventService.UpdateEvent(id, "NewName", _dbContext);
        _eventService.SoftDeleteEvent(id, _dbContext);

        return View(events);
    }
}

データサービス:

public class EventService : IEventService
{
    public IEnumerable<Event> AllEvents(IDbEntities entities)
    {
        return entities.Events.ToList();
    }

    public void UpdateEvent(Guid id, string name, IDbEntities entities)
    {
        var item = entities.Events.Find(id);
        if (item != null)
        {
            item.Name = name;
            entities.SaveChanges();
        }
    }

    public bool SoftDeleteEvent(Guid id, IDbEntities entities)
    {
        var item = entities.Events.Find(id);
        if (item != null)
        {
            item.Purged = true;
            entities.SaveChanges();
        }

        return true;
    }
}

DbContextインターフェース:

// This is an interface that my Entity Framework DbContext implements for Dependency Injection purposes
public interface IDbEntities
{
    DbSet<Event> Events { get; set; }
}
3
Mité

DbContextの場合と同じように、EventServiceコンストラクターに新しいEventControllerを注入する必要があります。

DbContextオブジェクトは、軽量で短命なオブジェクトです。 EventControllerからDbContextメソッドにEventServiceを渡すと、追加の利点を提供することなくクラス間の不要な結合が作成され、DbContextの寿命の管理はコントローラーの責任ではありませんとにかく。

コントローラーでDbContextが必要ない場合(コントローラーのコードが示唆しているように)、コントローラーに注入する必要はありません。

クラス境界は、DbContextの適切な抽象化レベルです。一般に、DbContextを他のクラスと共有しないでください。クラスインスタンスごとに新しいものを作成するだけです。

1
Robert Harvey