在ASP.NET 2.0中操作数据之五十二:使用FileUpload上传文件

导言:

  到目前为止,我们的教程围绕的是text数据。然而,很多应用程序既需要处理text数据,也需要处理二进制数据。比如招聘网站可能需要用户上传Word或PDF格式的简历。

  使用二进制数据面临一项挑战:在应用程序中如何存储二进制数据。我们必须更新添加记录的界面以支持用户上传本地电脑中的文件,并添加额外的功能以下载某条记录的相关二进制数据。本章以及接下来的3章,我们探讨如何处理这些问题。在本系列教程结束时,我们将创建一个功能完善的应用程序,它为每种类型的记录提供相关的图片和PDF小册子。 在本系列教程,我们探讨存储二进制数据的各种方法,考察如何允许用户从自己的电脑上传文件并存储在服务器的文件系统里。

  注意:二进制数据有时候被称为“BLOB”(Binary Large OBject的缩写)。本教程我选择使用术语“binary data”,即使它和术语BLOB同意。

第1步: 添加Working with Binary Data教程页

  我们先花一点时间在网站里创建一些页,这些页会在本教程里用到.先添加一个名为BinaryData的文件夹,然后添加如下页面.确保每页都选择了Site.master作为母板页.

Default.aspx
FileUpload.aspx
DisplayOrDownloadData.aspx
UploadInDetailsView.aspx
UpdatingAndDeleting.aspx


图1:添加所需要的页面

  象其它文件夹一样,BinaryData文件夹里的Default.aspx 用来列出教程章节.记得SectionLevelTutorialListing.ascx 这个用户控件提供了这个功能.因此,从解决方案浏览里将这个用户控件拖到页面上.


图2:添加SectionLevelTutorialListing.ascx 用户控件 到Default.aspx

最后,将这些页的地址加到 Web.sitemap 的条目里.在Enhancing the GridView <siteMapNode>之后添加下面的标记.

<siteMapNode
 title="Working with Binary Data"
 url="~/BinaryData/Default.aspx"
 description="Extend the data model to include collecting binary data.">

 <siteMapNode
 title="Uploading Files"
 url="~/BinaryData/FileUpload.aspx"
 description="Examine the different ways to store binary data on the
 web server and see how to accept uploaded files from users
 with the FileUpload control." />
 <siteMapNode
 title="Display or Download Binary Data"
 url="~/BinaryData/DisplayOrDownloadData.aspx"
 description="Let users view or download the captured binary data." />
 <siteMapNode
 title="Adding New Binary Data"
 url="~/BinaryData/UploadInDetailsView.aspx"
 description="Learn how to augment the inserting interface to
 include a FileUpload control." />
 <siteMapNode
 title="Updating and Deleting Existing Binary Data"
 url="~/BinaryData/UpdatingAndDeleting.aspx"
 description="Learn how to update and delete existing binary data." />

</siteMapNode>

修改完Web.sitemap后,在浏览器里看一下本教程站点。


图3:Site Map包含了本教程

第2步:将二进制数据存储在什么地方

  有2种方式存放二进制数据:一种是将其存储在服务器的文件系统里,并将文件路径存储在数据库里;第二种是直接将其存储在数据库里(见图4)。2种方法各有其优点和缺点。


图4:可以将二进制数据存储在文件系统或直接放在数据库

  假设我们对数据库Northwind进行扩展,每个产品对应一幅图片。一种方法是在服务器文件系统存储这些图片,然后在表Products里记录该图片的文件路径。为此,我们要在
Products表里添加一列,名为ImagePath,类型是varchar(200)。假设用户为产品Chai上传一张图片时,图片可能存放在服务器文件系统的~/Images/Tea.jpg位置。这里,~代表应用程序的物理位置。也就是说,如果该网站根植于C:/Websites/Northwind/的话,~/Images/Tea.jpg相当于C:/Websites/Northwind/Images/Tea.jpg 。上传图片后,我们应在表Products更新记录Chai,使其ImagePath列引用图片的路径。如果我们决定将所有产品的图片放在应用程序的Images文件夹,我们可以使用“~/Images/Tea.jpg”或“Tea.jpg”来表示。

将二进制数据放置在文件系统的主要优点在于:

1. 执行方便——就像我们即将看到的那样,将二进制数据直接放置在数据库和存储于文件系统相比,当用户需要存储并获取数据时需要更多的代码。另外,为使用户查看或下载数据,必须用到定位于该数据的URL(译注:统一资源定位器)。如果数据存储在文件系统,URL是直观明了的;如果是存储在数据库里,则必须创建一个页面来获取并返回数据。

2.访问范围宽——其它的服务或程序有时需要访问二进制数据,但当二进制数据存储在数据库中时,这些服务或程序便无法访问了。比如,用户可能希望通过FTP来访问每个产品对应的图片,在这种情况下,最好将其放置在文件系统。

3.更好的执行效能——将二进制数据放置在文件系统和数据库相比,在数据库服务和服务器服务之间的查询和网络堵塞情况要少一些。

  将二进制数据放置在文件系统的主要缺点在于削弱了数据的关联性。比如我们从表Products删除一条记录时,放在文件系统中的相关文件不会自动删除,因此我们必须手写代码将其删除。不然的话,随着文件碎片的慢慢积累,文件系统会变的混乱不堪。另外,对数据库的任何改动,都要对在文件系统里的相应二进制数据做修改。比如将数据库转移到另外的站点或服务器时便面临这种挑战。

  做为选择,你可以在Microsoft SQL Server 2005里创建一个类型为varbinary的列,用于存储二进制数据。你可以指定存储数据的最大长度,比如你希望数据的最大长度不超过5000字节,指定类型为varbinary(5000); 而varbinary(MAX)是Microsoft SQL Server 2005能提供的最大存储空间,大概 2 GB.

  将二进制数据存储在数据库的主要优点是:将数据库记录和二进制数据关联起来。它极大的简化了数据库的管理,比如将数据库转移到另一个网站或服务器。同样,当删除一条记录时,同时自动的删除了相关的二进制数据。

  注意:在Microsoft SQL Server 2000及更早本版,varbinary类型最大支持8000字节,要支持2GB的二进制数据,就要使用image类型了。在SQL Server 2005里引入MAX后,image类型已经开始被淡化了。尽管向后兼容,微软宣称将在SQL Server的后续版本中抛弃image类型。

  如果你使用的是较早的数据类型,你可能看见过image类型。在数据库Northwind里的表Categories有一个Picture列,可用来存储某个类的二进制图像文件。由于数据库Northwind起源于Microsoft Access以及SQL Server早期版本,所以Picture列的类型为image。

  本章及接下来的3章,我们2种方法都要用。表Categories已经有列Picture来存储类的二进制图片文件,我们还要一个额外的列BrochurePath来存储文件系统里PDF的路径。

第3步:为表Categories添加BrochurePath列

  目前,表Categories只包含了4个列:CategoryID, CategoryName, Description以及 Picture。除此以外,我们还需要添加一列,指向该类的小册子(如果存在的话)。打开服务器资源管理器,点击表节点,右键点击表Categories,选择“打开表定义”(见图5)。如果看不到服务器资源管理器,在视图菜单里选择它,或按Ctrl+Alt+S.

  在表Categories里添加一个名为BrochurePath的列,类型为varchar(200),允许其值为NULL。点击保存按钮(或按Ctrl+S)。


图5:表Categories里添加BrochurePath的列

第4步:更新体系构架以使用Picture 和 BrochurePath列

  当前,数据访问层(Data Access Layer)里的CategoriesDataTable定义了4个DataColumns:CategoryID, CategoryName, Description以及NumberOfProducts.我们最初在教程《创建一个数据访问层》里创建CategoriesDataTable时,其只包含了前3个列,而NumberOfProducts列是在第35章《使用Repeater和DataList单页面实现主/从报表》里创建的。

  就像在教材《创建一个数据访问层》里讨论的那样,DataTables以类型DataSet的形式构成了业务对象。TableAdapters的作用在于连接数据库,并以查询结果组成
业务对象。CategoriesDataTable是由CategoriesTableAdapter构成的,它包含三种数据访问方法:

  GetCategories():执行该TableAdapter的主要查询,返回记录的CategoryID, CategoryName和Description这3项。自动生成的Insert和Update方法主要就是用的该方法。

  GetCategoryByCategoryID(categoryID):也是返回记录的CategoryID, CategoryName和Description这3项,前提是CategoryID值要匹配。

  GetCategoriesAndNumberOfProducts():也是返回记录的CategoryID, CategoryName和Description这3项,同时返回每种类别产品的数量。

  我们注意到,这些方法没有返回表Categories的Picture或BrochurePath;CategoriesDataTable里也没有展示这些列。为了能够使用到Picture和BrochurePath,我们需要先在CategoriesDataTable里添加它们,再更新类CategoriesTableAdapter,使其返回它们的值。

添加Picture和BrochurePath列

  首先将它们添加到CategoriesDataTable.在CategoriesDataTable的顶部点右键,从菜单里选“添加”,再选“列”选项。这将为DataTable 创建一个名为Column1的数据列(DataColumn),将其重命名为Picture。在属性窗口里将其DataType属性设置为“System.Byte[]”(在下拉列表里没该选择,故需手动输入)


图6:创建一个名为Picture的数据列,设数据类型为System.Byte[]

添加另一个名为BrochurePath的数据列,使用默认的数据类型(System.String)

从TableAdapter返回值Picture和BrochurePath

  在CategoriesDataTable里添加了上述2列后,我们准备更新CategoriesTableAdapter。我们可以在TableAdapter的主查询里返回这2个值,但每次调用GetCategories()都会返回二进制数据。怎么才好呢?我们可以让主查询返回BrochurePath值,而另外创建一个方法来返回某个特定种类的Picture值。

  为了更新主查询,在CategoriesTableAdapter的顶部右键点击,选“配置”项,这将启动Table Adapter设置向导,更新查询使其返回BrochurePath,点完成。


图7:更新SELECT命令,返回BrochurePath

  使用ad-hoc SQL语句更新TableAdapter里的主查询时,它将更新TableAdapter里所有方法的查询涉及的列。也即,更新GetCategoryByCategoryID(categoryID) 方法,使其返回BrochurePath值;更新GetCategoriesAndNumberOfProducts()方法,并删除返回每种类别有几个产品的查询(也即删除NumberOfProducts)因此,我们右键点击GetCategoriesAndNumberOfProducts(),选择“配置”,使其恢复为原来的查询语句:

SELECT CategoryID, CategoryName, Description,
 (SELECT COUNT(*)
 FROM Products p
 WHERE p.CategoryID = c.CategoryID)
 as NumberOfProducts
FROM Categories c

  然后,创建一个返回某个特定种类Picture值的TableAdapter方法。在CategoriesTableAdapter的顶部点击右键,选择“添加查询”,这将打开TableAdapter的查询设置向导。首先选择如何访问数据库,有3种方式:使用SQL语句、创建一个新的存储过程、使用一个已有的存储过程。我们选择“使用SQL语句”,点下一步,在界面里选“SELECT(返回行)(S)”。


图8:选择使用SQL语句


图9:由于查询要返回一条记录,我们选“选择行”。

点下一步,键入如下SQL查询,点Next:

SELECT CategoryID, CategoryName, Description, BrochurePath, Picture
FROM Categories
WHERE CategoryID = @CategoryID

  最后,为新方法命名。为填充DataTable的方法命名为FillCategoryWithBinaryDataByCategoryID;为返回DataTable的方法命名为GetCategoryWithBinaryDataByCategoryID。点Finish完成设置。


图10:为TableAdapter的方法命名

  注意:完成设置后,我们将看到一个对话框,提示你“新命令文本所返回数据的架构与主查询的构架不同。如果不期望出现此情况,请检查查询的命令文本。”。简而言之,向导意识到主查询—GetCategories() ,和我们刚刚创建的方法返回的数据不同。这正是我们希望的结果,不用理会它。

  同时,谨记,如果你在向导里选用ad-hoc SQL语句,然后再改变TableAdapter的主查询,它将改变GetCategoryWithBinaryDataByCategoryID 方法里SELECT命令所涉及到的列,以包含主查询使用的那些列(也就是从查询里移除Picture列)。我们必须手动更新代码,使其返回Picture ,和我们在前面处理GetCategoriesAndNumberOfProducts() 方法类似。

  当完成在CategoriesDataTable添加2个数据列,以及对CategoriesTableAdapter添加GetCategoryWithBinaryDataByCategoryID方法后,这些类在数据集设计器里看起来应和图11差不多。


图11:DataSet Designer包含了新列和新方法

更新业务逻辑层(BLL)

更新数据访问层后,接下来就要扩展业务逻辑层以应对新添加的CategoriesTableAdapter方法,在类CategoriesTableAdapter添加如下代码:

[System.ComponentModel.DataObjectMethodAttribute
 (System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable
 GetCategoryWithBinaryDataByCategoryID(int categoryID)
{
 return Adapter.GetCategoryWithBinaryDataByCategoryID(categoryID);
}

第5步:从客户端上传一个文件到服务器

  通常情况下,用户将本地计算机上的文件上传到服务器,这就涉及到以何种形式来处理数据,是直接将它存储在数据库?还是将它存储在文件系统,然后在数据库存储其文件路径?在这里,我们探讨如何将文件上传到服务器,在后面的教程我们专注于上传文件的数据模式。

  ASP.NET 2.0新增加的FileUpload Web控件提供了一种机制,供用户上传文件。它是一种type属性为“file”的<input>元件。在浏览器里看起来就像是一个带Browse按钮的文本框。当点击Browse按钮后,便弹出一个对话框供用户选择文件。选定,回传后,被选文件的内容一起被传递会服务器。在服务器端,我们可以通过FileUpload控件的属性获取上传文件的信息。

  为验证上传文件,打开BinaryData文件夹的FileUpload.aspx页面并切换到设计模式。从工具箱拖一个FileUpload控件到页面,设其ID为UploadTest。再添加一个Button控件,设其ID为UploadButton,Text属性为“Upload Selected File”。最后,在Button控件下添加一个Label控件,设其ID为UploadDetails并清空Text属性。


图12:在ASP.NET页面上添加一个FileUpload控件

  图13为在浏览器查看该页面的情形,我们注意到,当点击Browse按钮时,弹出一个对话框,供用户选择要上传的文件。当选定一个文件,再点“Upload Selected File”按钮时,页面回传,将文件的二进制数据传到服务器。


图13:用户选择上传到服务器的文件

  页面回传后,上传的文件可以存储于文件系统,也能以“流”(Stream)的形式被调用。本例,我们将其存储在文件夹~/Brochures 里。首先在根目录创建一个Brochures文件夹,然后为UploadButton的Click事件创建一个事件处理器:

protected void UploadButton_Click(object sender, EventArgs e)
{
 if (UploadTest.HasFile == false)
 {
 // No file uploaded!
 UploadDetails.Text = "Please first select a file to upload...";
 }
 else
 {
 // Display the uploaded file's details
 UploadDetails.Text = string.Format(
 @"Uploaded file: {0}<br />
 File size (in bytes): {1:N0}<br />
 Content-type: {2}",
 UploadTest.FileName,
 UploadTest.FileBytes.Length,
 UploadTest.PostedFile.ContentType);

 // Save the file
 string filePath =
 Server.MapPath("~/Brochures/" + UploadTest.FileName);
 UploadTest.SaveAs(filePath);
 }
}

  FileUpload控件提供了多种处理上传数据的属性。比如,HasFile属性指出用户是否上传了文件;FileBytes属性以字节的形式访问数据。Click事件处理器事先确定是否上传文件,如果是,Label控件列出文件的名称、字节大小和类型。
  注意:为确保用户上传文件,可以使用RequiredFieldValidator控件或检查HasFile属性,若其为false,则提出警告信息。

  FileUpload控件的SaveAs(filePath)属性将文件存储在一个指定的文件路径(filePath)。路径必须是一个物理路径(如C:/Websites/Brochures/SomeFile.pdf)),而不是相对路径(如:/Brochures/SomeFile.pdf). 方法Server.MapPath(virtPath)截取的是相对路径,返回的是物理路径。这里,相对路径是~/Brochures/fileName, 其fileName就是上传文件的名字。

  完成Click事件处理器后,花几分钟在浏览器查看该页,点Browse按钮,从硬盘选择一个文件供上传。再点“Upload Selected File”按钮,页面回传,将文件上传到 ~/Brochures文件夹里。上传文件后,返回Visual Studio,在解决资源管理器里点“刷新”按钮,你将会在~/Brochures文件夹里看到刚刚上传的文件。


图14:文件已经上传到服务器


图15:上传文件保存在~/Brochures文件夹

将上传文件保存在文件系统

  当将上传文件保存到文件系统时,有几个要点需要注意。首先是安全问题,要将文件保存到文件系统,运行的页面必须要有写入权限。如果你使用Microsoft's Internet Information Services (IIS) 当服务器,其安全性取决于IIS的版本和设置。

  另一个挑战是对上传文件的命名问题。一般来说,页面将文件保存在~/Brochures 文件夹时,直接使用其在用户电脑时的原名。比如,用户A上传一个名为Brochure.pdf的文件,上传后保存为~/Brochure/Brochure.pdf,假如稍后用户B也要上传文件,且名称也刚好为Brochure.pdf,会发生什么情况呢?就我们目前的代码而言,用户B的文件将覆盖用户A的文件。

  有几种处理命名冲突的方法。一种是当存储同名文件时,阻止上传文件。比如当用户B试图上传一个名为Brochure.pdf的文件时,提示其改名并重试。另一个方法是使用一种唯一标识的文件名,可以是globally unique identifier (GUID),或对应数据库记录的主键值。在下一节教程我们将详细探讨。

处理大容量二进制数据的面临的问题

  教程假设处理的二进制数据是适度大小的。处理大数据量的二进制数据时—比如几MB,甚至更大,就超出本教程的范围了。默认情况下, ASP.NET 最多处理4MB的数据,虽然可以在Web.config文件的<httpRuntime>元素里设置能处理的最大值,但IIS同样对上传文件的大小做了限制,见文章《IIS Upload File Size》。
另外,上传大数据量文件花费的时间很可能超过ASP.NET默认等待的110秒,还要面对处理大数据的内存、执行效率问题。

  FileUpload控件不太适合上传大的文件。当上传大文件时,用户需要耐心的等待,且无法确定上传是否在进行。上传小文件时问题不大,也许只要几秒钟;而大文件可能要几分钟。有很多第三方的文件上传控件更适合上传大文件且提供进度提示,提供更好的用户体验。

  如果你的应用程序需要处理大文件,你要认真考虑面临的挑战,寻找适合自己的解决方案。

总结:

  创建一个处理二进制数据的应用程序面临一些问题。本教程探讨了其中的2个问题:如何存储数据以及允许用户通过页面上传文件。接下来的教程我们探讨如何处理数据库记录中的二进制数据,以及如何显示它。

  祝编程快乐!

作者简介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。大家可以点击查看全部教程《[翻译]Scott Mitchell 的ASP.NET 2.0数据教程》,希望对大家的学习ASP.NET有所帮助。

(0)

相关推荐

  • 在ASP.NET 2.0中操作数据之五十六:使用ObjectDataSource缓存数据

    导言 就计算机科学而言,caching就是将所需要的数据或信息的备份放在某个地方,便于快速访问的这样一个过程.以数据处理(data-driven)程序为例,程序的大部分时间浪费在数据查询上.要提升这种程序的性能,通常的做法是将查询结果存放在程序的存储器里. ASP.NET 2.0提供了各种各样的缓存方式.对web页面和用户控件可以通过output caching进行缓存:同样我们可以通过ObjectDataSource 和SqlDataSource控件,在控件级(control level)对数

  • 在ASP.NET 2.0中操作数据之五十五:编辑和删除现有的二进制数据

    导言: 在前面的3章里我们为处理二进制数据添加了很多的功能.我们首先在表Categories里添加BrochurePath列,并更新了体系结构.同样,为了处理表Categorie里现有的Picture列,我们在数据访问层和业务逻辑层里增加了相应的方法.同时我们创建一个页面,在GridView控件里显示二进制数据--包含一个指向说明小册子的下载链接,并将每个类的图片显示在<img>元素里.同时我们添加一个DetailsView控件,供用户添加新的类,并上传其图片和小册子数据. 剩下的就是添加编辑

  • 在ASP.NET 2.0中操作数据之五十一:从GridView的页脚插入新记录

    导言: 正如教程<概述插入.更新和删除数据>里探讨过的一样, GridView, DetailsView和FormView Web控件都有内置的修改数据的功能.当声明绑定到数据源控件时,可以快速而方便地修改数据--甚至不用写一行代码.不幸的是,只有DetailsView和FormView控件提供了内置的插入.编辑.删除功能,而 GridView控件只支持编辑.删除功能.不过,稍许努力,我们就能使GridView控件包含一个插入界面. 为了给GridView添加插入功能,我们要决定如何添加新记录

  • ASP.NET 站点地图(sitemap)简明教程

    还好,现在有这个机会,就权当自己的笔记吧!.以下讲一下最简单的创建形式. 站点地图,在每一个网站都必须用的一种技术.它是用来给用户导航作用的,以便告诉用户现在的位置.特别是对那些目录很深的网页,这种效果就犹为明显. 比如 天涯社区>天涯论坛>海口...这种形式. 1.新建一个站点地图(和新建aspx一样),tour.sitemap.下面是默认情况生成的xml文件. 复制代码 代码如下: <?xml version="1.0" encoding="u

  • 在ASP.NET 2.0中操作数据之五十八:在程序启动阶段缓存数据

    导言: 前面2章考察了在表现层和缓存层缓存数据.在第56章,我们探讨了在表现层设置ObjectDataSource的相关cache属性来缓存数据.在第57章,我们探讨了创建一个单独的分开的缓存层.这2章都是采用"应激装载"(reactive loading)的模式来缓存数据.该模式下,每次请求数据时,系统先检查其是否在内存,如果没有,则从数据源--比如数据库,来获取数据,然后将其存储在内存里.该模式的优势在于执行起来很容易:而缺点之一在于应"请求"(requests

  • 在ASP.NET 2.0中操作数据之五十七:在分层架构中缓存数据

    导言: 正如前面章节所言,缓存ObjectDataSource的数据只需要简单的设置一些属性.然而,它是在表现层对数据缓存,这就与ASP.NET page页面缓存策略(caching policies)紧密的耦合(tightly couples)起来.我们对体系机构分层的原因之一便是打破这种耦合.拿业务逻辑层为例,将业务逻辑从ASP.NET页面脱离出来:而数据访问层将数据访问的细节ASP.NET页面脱离出来.从某种意义来说,将业务逻辑和数据访问细节脱离出来是首先,这样的话使系统更易读.易维护.易

  • 在ASP.NET 2.0中操作数据之六十:创建一个自定义的Database-Driven Site Map Provider

    导言: ASP.NET 2.0的网站地图(site map)功能允许页面开发者在一些持久介质(persistent medium),比如一个XML文件里,自己定义一个web程序的site map.一旦定义了之后,我们可以通过System.Web命名空间的SiteMap class类或某个Web导航控件,比如SiteMapPath, Menu, 或TreeView来对其进行访问.site map系统使用的是provider model模式,所以可以创建不同的site map,并将其应用到一个web

  • 在ASP.NET 2.0中操作数据之五十三:在Data Web控件显示二进制数据

    导言: 在前面的教程我们阐述了应用程序处理二进制数据的2种模式,以及使用FileUpload 控件从浏览器向服务器文件系统上传文件.当文件上传并存储在文件系统里时,应在相应的数据库记录里存储该文件的存储路径. 我们先来看如何为最终用户提供二进制数据.怎样展示二进制数据呢?这取决于其类型.比如图片,我们将其显示为image:如果是PDFs,Microsoft Word文档.ZIP文件或其它类型的数据,或许提供一个"Download"链接比较妥当. 在本节,我们看如何在GridView和D

  • 在ASP.NET 2.0中操作数据之五十四:添加新记录时包含一个文件上传选项

    导言: 在前面2节教程,我们探讨了如何使用FileUpload控件从客户端向服务器上传文件,以及如何在数据Web控件里显示二进制数据. 在本节,我们将创建一个web页面以添加新的种类.除了为类的name和description属性添加TextBoxes控件外,我们还要在页面上添加2个FileUpload控件--一个用来上传新类的图片,另一个用来上传类的小说明册子.上传的图片将直接存储在新记录的Picture列.与此相反,小册子将存储在~/Brochures 文件夹,同时将文件路径存储在新记录的B

  • 在ASP.NET 2.0中操作数据之五十九:使用SQL缓存依赖项SqlCacheDependency

    导言: 在56和57章探讨的缓存技术使用的是基于时间的缓存周期,当过了某段时间后便将缓存数据从内存清除.当设置缓存时间为x秒时,数据在x秒内都是"新"的.当然,就像在60章谈到的那样,对静态数据来说,x可延伸到web应用程序的整个生命周期(lifetime). 当缓存数据时,基于时间周期的技术因为其易用性而常常被采用,不过又常常不那么完美.理想的状态是这样的:数据库数据还是应缓存在内存,直到源数据(underlying data)发生改变时才从内存清除.这样的话可以最大化的获取缓存带来

随机推荐