zoukankan      html  css  js  c++  java
  • [翻译]ASP.NET MVC 3 开发的20个秘诀(二十)[20 Recipes for Programming MVC 3]:缓存结果数据加速页面载入

    议题

    随着网站的发展,大量用户访问流行内容和动态内容,这两个方面的因素会增加平均的载入时间,给Web服务器和数据库服务器造成大量的请求压力。而大量的数据请求就需要强大的数据库处理能力来支撑。改进更加只能的程序,以极少不必要的数据库访问或动态处理请求,可以节省添加更多服务器的费用以及显著提高Web应用程序的整体速度。

    解决方案

    实现OutputCacheAttribute类,缓存不经常改变的数据或者相对固定的动作。

    讨论

    MVC3中实现缓存是非常容易的事情。将下面的属性添加在某个控制器的动作上即可完成:

    [OutputCache (Duration=600)]

    这个语句将自动缓存该视图600秒(或10分钟)共享给每个访问此页的用户。这就意味着针对代码进行简单的修改当你有1000名用户同时访问此页,只需要通过一次数据加载,可节约数以千计的数据库请求以及IIS处理负载。

    输出缓存的属性看起来非常简单,但是当你打开引擎盖的时候,也可能会发现这辆车的引擎原来如此复杂。当然除非你原本就是名机械师。这个属性提供了很多关于缓存的方式,必须持续缓存时间,甚至还添加了SQL依赖,在这个秘诀中我们会深入探讨一番。

    按照时间缓存非常简单,你只需要告诉MVC视图应该被缓存多少秒即可。至于缓存存储的位置,是客户端浏览器还是服务器或者是它们的组合,这个问题稍微有点复杂。一个好的做法是首先分析被缓存的内容数据,如果是缓存多个用户共享的数据,缓存到服务器上更为合适;然而如果是个人数据,比如个人定制的网页,还是将其缓存在用户的浏览器中更好。虽然缓存可以说是个伟大的发明,但是它也是有局限性的。通常情况下,缓存的最大限制是内存,不是一切都可以缓存在服务器上。

     

    然而,最有趣的方式还是SQL依赖。OutputCache允许数据一直被缓存,直到它在数据中的内容发生了实际的变化,这是一个非常有用的功能。就拿图书来举例,新书并不是经常增加的,因此可以为图书设置一个缓存时间(例如24小时)。但是,如果在缓存过期之前添加了一本新书,又或者是在漫长的一周或几天里根本就没有添加新书?第一种情况,添加一本新书不能及时出现,用户是会不高兴的。而第二种情况,因为没有新书被添加,每天都要发起不必要的服务器请求。使用SQL依赖的方式,像我们希望的那样,当图书的表发生变化时缓存能被立即更新。

    这是一个非常棒的功能,在其他编程语言中,你需要手动控制缓存,你需要自己手动更新无效缓存。相信我,这很容易就会让你错过一两个应该正常清除的缓存。

    在接下来的示例中,将缓存图书列表页面。默认情况下,如果没有设置VaryByParam的值,MVC3将会自动创建一个唯一的缓存对象。这是个相当棒的功能,按二在这本书上面的例子里,搜索关键字也会作为输入参数之一,但是可能输入数以百计不同的关键字组合,所以这个变量不应该被缓存(这就是上面提高的会产生内存警告的问题)。下面修改后启用缓存的BooksController控制器:

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Dynamic;
    using System.Web;
    using System.Web.Mvc;
    using MvcApplication4.Models;
    using MvcApplication4.Utils;
    using PagedList;
    namespace MvcApplication4.Controllers
    {
    public class BooksController : Controller
    {
    private BookDBContext db = new BookDBContext();
    //
    // GET: /Books/
    [OutputCache(Duration=600, VaryByParam=
    "sortOrder;filter;page")]
    public ViewResult Index(string sortOrder,
    string filter, string Keyword, int page = 1)
    {
    ...
    return View(books.ToPagedList(currentPage,
    maxRecords));
    }
    ...
    }

    }

    这段代码是非常不错的缓存方案,可以立即降低服务器负载。接下来,将这个例子扩展为SQL依赖,在开始工作之前必须还要做一些设置工作。首先是修改Web.config,在文件中定义一个数据库链接,然后,将缓存部分的SQL依赖设置如下:

    <?xml version="1.0"?>
    <configuration>
    <connectionStrings>
    <add name="ApplicationServices" connectionString=
    "data source=.\SQLEXPRESS;Integrated Security=SSPI;
    AttachDBFilename=|DataDirectory|aspnetdb.mdf;
    User Instance=true"
    providerName="System.Data.SqlClient"
    />
    <add name="BooksDBContext" connectionString=
    "Server=.\SQLEXPRESS;Database=
    MvcApplication4.Models.BookDBContext;
    Trusted_Connection=true"
    providerName=
    "System.Data.SqlClient"
    />
    </connectionStrings>
    ...
    <system.web>
    <caching>
    <sqlCacheDependency enabled="true" pollTime="2000">
    <databases>
    <add name = "MvcApplication4.Models.BookDBContext"
    connectionStringName
    = "BooksDBContext"/>
    </databases>
    </sqlCacheDependency>
    </caching>
    ...
    </system.web>
    ...
    </configuration>

    在上面的例子中,将pollTime设置为2000毫秒,也就是说,每2秒中,就会查询一次缓存数据库是否被更改,这个变量设置可以根据你的实际需求来修改。

    现在,需要修改Global.asax.cs文件,必须在Application_Start方法中通过SqlCacheDependencyAdmin类的EnableTableForNotifications方法为每个需要缓存的表添加监听功能。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;
    using MvcApplication4.Models;
    using System.Data.Entity;
    using System.Globalization;
    using System.Threading;
    using MvcApplication4.Utils;

    namespace MvcApplication4
    {
    public class MvcApplication : System.Web.HttpApplication
    {
    ...
    protected void Application_Start()
    {
    Database.SetInitializer<BookDBContext>(
    new BookInitializer());

    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);

    RegisterRoutes(RouteTable.Routes);

    String connectionString =
    System.Configuration.ConfigurationManager.ConnectionStrings
    ["BooksDBContext"].ConnectionString;

    System.Web.Caching.SqlCacheDependencyAdmin.
    EnableNotifications(connectionString);

    System.Web.Caching.SqlCacheDependencyAdmin.
    EnableTableForNotifications(connectionString, "books");
    }
    ...
    }

    }

    在命令行窗口中,执行如下步骤来完成SQL通知的功能配置工作:

    点击“开始”按钮 -> 选择“运行”

    输入“cmd”并回车

    cd %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regsql.exe -S .\SQLEXPRESS -ed-dMvcApplication4.Models.BookDBContext -et -t books -E

    务必要你自己的信息,替换命令中的服务器名、数据库名以及表名。此外,如果你的数据库包含用户名和密码,将需要包含额外的输入参数(-U-P)。命令运行后,应该会显示两条成功信息,第一条,说明数据库缓存功能启用;第二条说明指定表缓存成功。

    最后,使用SQL依赖缓存需要对BooksController稍作修改。此外,因为更换应用程序缓存方式,之前设置的缓存持续时间需要修改为Int32的最大值。

    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.Entity;
    using System.Linq;
    using System.Linq.Dynamic;
    using System.Web;
    using System.Web.Mvc;
    using MvcApplication4.Models;
    using MvcApplication4.Utils;
    using PagedList;

    namespace MvcApplication4.Controllers
    {
    public class BooksController : Controller
    {
    private BookDBContext db = new BookDBContext();
    //
    // GET: /Books/
    [OutputCache(Duration=Int32.MaxValue, SqlDependency =
    "MvcApplication4.Models.BookDBContext:books",
    VaryByParam="sortOrder,filter,page")]
    public ViewResult Index(string sortOrder, string filter,
    string Keyword, int page = 1)
    {
    ...
    return View(books.ToPagedList(currentPage,
    maxRecords));
    }
    ...
    }
    }

    在以前的MVC版本中,是不支持局部缓存的,这就意味着每次都需要将整个动作的结果进行缓存。目前在MVC3版本中开始支持局部缓存。实现这个功能,需要创建一个类似于秘诀1.14中使用Ajax提交表单的自动作。在BookCommentsController的这两个活动都至返回分部视图,而都无需缓存父级动作中的缓存内容。这是一个非常棒的改进,可以将你的代码与那些不经常改变的缓存内容进行有效的隔离。

    参考

    OutputCacheAttribute SqlCacheDependencyAdmin 原书地址 书籍源代码

    如果你现在正在用asp.net mvc 3 开发web程序,想让自己的页面有比较好的效果但是对CSS不熟悉的话,可以参考以下视频。

    很简单的设置可以做出比较不错的效果。

    http://www.youtube.com/watch?v=0O0gi2m_p_o&feature=player_embedded

    免费模板网址

    http://www.freecsstemplates.org/

    我做了几个比较简单的例子

    示例代码如下:

     https://files.cnblogs.com/huyq2002/CSSTemplate.zip

    如果要替换模板

    1)把下载下来的images拷贝到对应的image目录

    2)拷贝style.css里面的代码到程序里面的site.css

    3)运行程序,点击刷新按钮(一定要点刷新看新的模板效果)

    在VS2010中利用Asp.net MVC自带的模板生成的菜单是固定的,没办法更改,下面利用PartialView实现简单的一级菜单。

    1) 修改_Layout.cshtml,在<nav>部分改成@{ Html.RenderAction("Menu", "Home");}

    <div class="float-right">
          <section id="login">
                @Html.Partial("_LogOnPartial")                      
          </section>
                  <nav>   
                     @{ Html.RenderAction("Menu", "Home");}                       
                  </nav>
    </div>

      MVC将会调用HomeController的Menu方法来显示菜单

    2)在HomeController里面添加Menu方法,返回PartialView

    public PartialViewResult Menu()
    {
    List<MenuItem> menus = new List<MenuItem>();
    menus.Add(new MenuItem{ Text="Home", Controller="Home", Action="Index"});
    menus.Add(new MenuItem { Text = "Job", Controller = "Job", Action = "Index" });
    menus.Add(new MenuItem { Text = "About", Controller = "Home", Action = "About" });
    menus.Add(new MenuItem { Text = "Contact", Controller = "Home", Action = "Contact" });
    return PartialView(new MenuModel { Menus = menus });
    }

    3) 定义一个新的PartialView ,名称为Menu.cshtml,基于原来自动生成的代码修改为:

    @model MVCDemo.Models.MenuModel
    <ul id="menu">
        @foreach (var item in Model.Menus)
        {
        <li>@Html.RouteLink(item.Text, new { controller = item.Controller, action = item.Action })</li>
        }
    </ul>

    利用PartialView可以实现自定义多级菜单,并且权限控制也很容易。 

    完整代码如下:

     https://files.cnblogs.com/huyq2002/MVCDemo.zip

     运行该示例可能需要安装asp.net MVC4


  • 相关阅读:
    668. Kth Smallest Number in Multiplication Table
    658. Find K Closest Elements
    483. Smallest Good Base
    475. Heaters
    454. 4Sum II
    441. Arranging Coins
    436. Find Right Interval
    410. Split Array Largest Sum
    392. Is Subsequence
    378. Kth Smallest Element in a Sorted Matrix
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2320048.html
Copyright © 2011-2022 走看看