MVC3データコンテキストのベストプラクティス

これは私のコントローラーにある行動です。モデルのデータアクセスレイヤーでこのアクションを実行することによって抽象化するのではなく、このコントローラーの内部でデータベース接続(つまり、MySqlデータベースへの接続であるPhotoGalleryContext)を作成して処理することは悪い習慣と考えられますか? csクラス?

   //GET: /Admin/GetPhoto/id
    public ActionResult GetPhoto(int id)
    {
        PhotoGalleryContext db = new PhotoGalleryContext();

        Models.PhotoGallery.Photo photo = new Models.PhotoGallery.Photo();
        photo = db.Photos.Where(p => p.PhotoId == id).Single();

        string filePath = photo.FileLocation;

        db.Dispose();    

        byte[] byteArray;
        try
        {
            byteArray = System.IO.File.ReadAllBytes(filePath);
            return File(byteArray, "image/jpg");
        }
        catch (Exception)
        {
            //throw;
        }
        return null;
    }
1
disposeを表示するために、貼り付けエラーをコピーし、編集しました
追加された 著者 Travis J,
db(PhotoGalleryContext)をどこで処分していますか?この例ではありませんか?
追加された 著者 DaveShaw,

2 答え

これを決めるときは、おそらくアプリケーションのサイズを考慮する必要があります。私はモデルを分けることがベストプラクティスだと言いますが、小さなアプリケーションの場合は、 PhotoGalleryContext をusingブロックにラップしてください。

using(PhotoGalleryContext db = new PhotoGalleryContext())
{

    Models.PhotoGallery.Photo photo = new Models.PhotoGallery.Photo();
    photo = db.Photos.Where(p => p.PhotoId == id).Single();

    string filePath = photo.FileLocation;
    byte[] byteArray;
    try
    {
        byteArray = System.IO.File.ReadAllBytes(filePath);
        return File(byteArray, "image/jpg");
    }
    catch (Exception)
    {
        //throw;
    }
    return null;
}
2
追加された
これをモデルに分けていたら、このようなコントローラーの中で毎回PhotoGalleryManagerクラスをインスタンス化し、最後にそれを破棄するだけですか?私のマネージャに多くの異なる操作が含まれている場合、このような軽量のマネージャクラス全体を読み込むのが遅くなるでしょうか?
追加された 著者 Travis J,
.dispose()を呼び出すよりも()を使用していますか?
追加された 著者 Travis J,
using()は、最後の括弧でDispose()を呼び出します.imoは、コードの書式を入れ子にしている限り、コードを少し読みやすくします。
追加された 著者 danludwig,

あなたのアプリケーションのサイズに依存するという点で、Davidに同意してください。

しかし、私はあなたのための接続を管理するために依存性注入を使用することをお勧めします。

StructureMap のようなものを使用すると、次のようなことができます。

For()
   .HybridHttpOrThreadLocalScoped
   .Use();

これは、

何かが PhotoGalleryContext を要求すると、( PhotoGalleryContext )を HTTPスコープ終了)。

これにより、StructureMapは自動的に接続を開いたり閉じたりします。

コントローラは次のようになります。

private readonly PhotoGalleryContext _db;
public AdminController(PhotoGalleryContext db)
{
   _db = db;
}

あなたの行動方法では、 _db はあなたのために行く準備ができています。

アプリケーション全体で多くの繰り返し使用ステートメントを節約するコード行はほとんどありません。

1
追加された
@ TravisJ - いいえ、Viewのレンダリングは依然として現在のHTTPリクエストの一部であるため、ただし、それは悪い習慣です。あなたのビューは、DB接続を知らない/気にしないでください。なぜモデルはctxの浅いコピーを使用しますか?
追加された 著者 RPM1984,
@ TravisJ - あなたのニットピッキング今思う。私はStructureMapが要求時間にあまりにも多くのオーバーヘッドをどのように追加するのか分かりません。はい、使用すると接続時間が短くなります。しかし、パフォーマンスが心配ならば、データベースクエリ、HTTPリクエストなどのコア領域に集中する必要があります。早すぎる最適化は死です。私はまだあなたがなぜ浅いコピーを作る必要があるのか​​分からない。ビューに表示されるViewModelsにデータベースオブジェクトをマッピングする必要があります。その後、元のオブジェクトにデータを保存することについて心配する必要はありません。
追加された 著者 RPM1984,
これはエレガントなソリューションです、ありがとうございます。
追加された 著者 Travis J,
私がまだデータベースコンテキストの浅いコピーを使用しているモデルを返すと、処分が呼び出されないようになりますか?
追加された 著者 Travis J,
dbオブジェクトの一部を返すオブジェクトとコピーするオブジェクトを作成する場合、浅いコピーがコンテキスト内に保持されます。私はハードコピーを作成して、dbオブジェクトが破棄されたときにデータがまだ私のコピーに残っていることを確認していますが、自動的にガベージコレクションされていなければ、
追加された 著者 Travis J,
私はコードがより読みやすくなるかもしれませんが、大量のオーバーヘッドを使わなくてもいいと思っていました。それは、StructureMapが合計要求時間に追加されるようです。 HybridHttpOrThreadLocalScopedは自明ではありません。
追加された 著者 Travis J,