私の現在のアプリは、EF 4.1 Code First と Oracle バックエンドで .NET MVC3 を使用しています。複数の画像を表示する View がある 1 つのシナリオを除いて、すべてが事実上常に正常に機能します。すべての画像が正常に読み込まれる場合もあれば、読み込みに失敗する場合もあり、「接続が閉じられていませんでした」または「接続を開く必要があります」という 2 つのエラー メッセージのいずれかが表示されます。イメージは、サーバーのファイル システムではなく、BLOB としてデータベースに格納されます。ドキュメント (画像) のコレクションを含むビュー モデルがあり、EditorTemplate を使用してコレクションをビューにレンダリングします。レンダリングされたコードは、Controller アクションを呼び出して、コレクション内の各画像を取得します。コレクションをレンダリングする Razor コードは次のとおりです。
親ビュー:
<div id="carousel1" class="data-carousel">
@Html.EditorFor(x => x.Documents)
</div>
エディター テンプレート:
<div>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="@Url.Action("GetImage", "Product", new {docId = Model.DocumentID, width = 250, height = 250})" alt=""/>
</div>
このコードはブラウザに書き込まれます
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=1&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=2&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=3&width=250&height=250" alt=""/>
<img style="border: solid; border-color: lightgrey; border-width: thin" src="http://localhost:9613/Product/GetImage?docId=4&width=250&height=250" alt=""/>
ご覧のとおり、これにより、id を含むいくつかのパラメーターを、画像をバイト配列として返すアクション メソッドに渡すリンクが作成されます。
public void GetImage(int docId, int width, int height)
{
// Load image from database
var doc = productRepository.Documents.SingleOrDefault(f => f.DocumentID == docId);
var image = doc.FileContent;
new WebImage(image)
.Resize(width, height, true, true)
.Crop(1, 1)
.Write();
}
何が起こっているのかは、コントローラーアクションが各イメージ (潜在的に最大 10) に対して呼び出されており、次の要求が来る前にデータベース接続が閉じられていないことだと確信しています。 「using」ステートメントで Context の新しいインスタンスを使用して、これが改善されるかどうかを確認しますが、改善しませんでした。それで、私にできることはありますか?おそらく新しい非同期を見る必要がありますか、それともビューで複数の画像を取得するために使用できる他のパターンがありますか?
ティア
編集:
アプリケーションは IIS7 でホストされ、クラシック パイプライン モードの独自のアプリケーション プールがあります。StructureMap を IoC コンテナーとして使用するため、これによって DbContext の作成と有効期間が制御されます。Controller がインスタンス化されると、インスタンス化が行われます。
SM セットアップ:
public static class StructuremapMvc
{
public static void Start()
{
var container = (IContainer)IoC.Initialize();
DependencyResolver.SetResolver(new SmDependencyResolver(container));
}
}
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(scan =>
{
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
x.For<IProductRepository>().Use<ProductRepository>();
x.For<IProductContext>().Use<ProductContext>();
});
return ObjectFactory.Container;
}
コントローラ:
public class ProductController : Controller
{
private readonly IProductRepository productRepository;
public ProductController(IProductRepository productRepository)
{
this.productRepository = productRepository;
}
public void GetImage(int docId, int width, int height)
{
// Load image from database
var doc = productRepository.Documents.SingleOrDefault(f => f.DocumentID == docId);
var image = doc.FileContent;
new WebImage(image)
.Resize(width, height, true, true)
.Crop(1, 1)
.Write();
}
// etc.
}
リポジトリ:
public class ProductRepository : IProductRepository
{
private readonly IProductContext productContext;
public ProductRepository(IProductContext productContext)
{
productContext = productContext;
}
public IQueryable<Document> Documents
{
get { return productContext.Documents; }
}
// etc.
}
環境:
public class ProductContext : DbContext, IProductContext
{
// DbSets
public IDbSet<Document> Documents { get; set; }
public void SetModified(object entity)
{
Entry(entity).State = EntityState.Modified;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// etc.
}
// etc.
}