我当前的应用程序使用带有 EF 4.1 Code First 和 Oracle 后端的 .NET MVC3。除了在一个场景中,我们有一个显示多个图像的视图,几乎所有时间都运行良好。有时所有图像都加载正常,有时其中一些无法加载,我收到 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 在内的一些参数传递给 action 方法,该方法将图像作为字节数组返回:
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 个)都调用了 Controller 操作,并且在下一个请求到来之前没有关闭 db 连接。我尝试在存储库上创建一个方法来创建在“使用”语句中创建一个新的上下文实例,看看这是否会改善事情,但事实并非如此。那么有什么我可以做的吗?我应该查看新的异步,还是可以使用其他模式来检索视图中的多个图像?
TIA
编辑:
该应用程序托管在 IIS7 中,并在经典管道模式下拥有自己的应用程序池。我使用 StructureMap 作为 IoC 容器,因此它控制 DbContext 的创建和生命周期。实例化发生在控制器被实例化时:
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.
}