【发布时间】:2015-12-29 23:44:44
【问题描述】:
我创建了一个控制器来从我的数据库中检索图像,并成功地检索到了图像:
public class ImageController : Controller
{
[Route("user/{userId:int}/profile", Name = "GetUserProfileImage")]
public ActionResult UserProfileImage(int userId)
{
using (var imgRepo = new ImageRepository())
{
UserProfileImage img = imgRepo.GetUserImage(userId);
return File(img.Image, "image/jpg");
}
}
}
ImageRepository 在创建 DBContext 时对其进行实例化,并在释放 DBContext 时将其释放。
因此,我有一个显示用户列表的视图,并且对于每个用户,我都会像这样显示他们的图片:
@model IEnumerable<UserRankingViewModel>
<table class="table">
<tr>
<th>
#
</th>
<th>
@Html.DisplayNameFor(modelItem => modelItem.First().Name)
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.RankingPosition)
</td>
<td>
<img src="@item.ImageUrl" class="img-circle img-nav">
@Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
}
</table>
其中@item.ImageUrl 是指向GetUserProfileImage 路由的Url。如果我要列出 50 个用户,那么将向该路由发出 50 个请求,我猜 DBContext 将被查询 50 次以获取用户图像。
对于这种特殊情况,是否可以在内存中存储 UserProfileImage 列表以避免每次都查询数据库?这是一个不好的做法吗?如果是,为什么?
在我的情况下,除此之外没有其他应用程序/网络服务可以更改数据库数据,因此如果用户更新他们的图片,我可以检查其中是否有任何内存中图片列出并更新它,除了更新数据库。
【问题讨论】:
-
您可以使用 System.Web.Caching 命名空间缓存图像列表。
-
您可以加载所有图像并使用
Base64格式将它们传递给查看。您还可以在文件系统中缓存图像并使用文件系统返回文件结果。 -
不要混淆客户端缓存(由浏览器处理)和服务器缓存(由服务器处理)。我说的是服务器缓存。您可以让控制器首先检查缓存中是否存在图像列表,如果不存在,则调用图像存储库以检索列表并将其添加到缓存中。任何后续请求都将从缓存中检索图像列表,而不是命中数据库。您可以让缓存在设定的时间间隔后过期,或者只使用滑动过期并在每次更新/删除/添加图像时自己显式地使缓存无效。
-
我认为您的 IEnumerable
模型的最佳实践是将图像加载到此模型中以在唯一查询中显示 -
如果你把关注点分开,那么它就不会混淆。例如,如果您使用文件系统,那么您的操作的工作是首先检查文件系统上是否存在该项目,然后返回它,否则首先简单地从数据库中获取数据,然后将其放入文件系统并返回它。您还可以在需要时使整个缓存或缓存项无效。例如,您可以创建一个操作来重新创建文件系统,并在需要时从您的站点控制面板调用它。或者您可以在用户图像更改时使用户图像无效。或者您可以制定一个使文件系统失效的计划。
标签: c# asp.net-mvc entity-framework