在 ASP.NET 1.x 中,存储用户信息唯一可行的方式是创建你自己的数据访问组件,这很有用。从 ASP.NET 2.0 开始,又多了一个选择,那就是使用用户配置。ASP.NET 会自动使用一个后台的数据源来处理指定用户的数据(读取、更新)。
从概念上看,用户配置和自定义数据组件非常类似,但它更为简介方便。它和 ASP.NET 验证模型浑然一体,当需要时,用户信息会自动获得,如果用户信息被修改过,当前请求结束时会自动被写会数据库中。
在使用用户配置之前,你需要仔细对它进行评估。
1. 用户配置的性能
ASP.NET 用户配置功能的目标就是提供一个透明的方式管理用户的信息,你不需要使用 ADO.NET 数据类编写自己的数据库访问代码。遗憾的是,很多功能看上去方便,但性能和可扩展性却不尽如人意。
用户配置的扩展性问题完全取决于你需要存储的数据量和你计划访问数据的频率。
用户配置通过两种方式加入网页的生命周期:
- 程序中第一次访问用户配置对象时,ASP.NET 会从数据库取回当前用户的所有配置数据。至此,后续操作再也无需访问数据库
- 如果更改了任意的用户配置数据,更新会推迟到页面处理完成之后进行。PreRender、PreRenderComplete、Unload 事件释放了当前页面之后,用户配置被写回数据库
用户配置功能没有与缓存集成,因此每次使用用户配置数据的请求都需要一次数据库连接。
下面两个条件都成立,用户配置性能最佳:
- 只有相对较少的访问用户配置数据的页面
- 只存储少量数据
反之,用户配置的执行效率就会下降:
- 大量的页面需要访问用户配置信息
- 存储大量的信息。如果一次请求只需要其中一小部分数据,效率会更低(用户配置模型总是会取回用户配置信息的所有部分)
2. 用户配置如何存储数据
其实,用户配置如何被序列化才是它真正的限制。ASP.NET 默认包含的用户配置提供程序将用户配置信息序列化为一个数据块,并作为一个单独字段插入到数据库中。比如,序列化地址信息,会得到类似下面的结果:
Marty Soren315 Southpart DriveLompocCalifornia93436U.S.A
另外一个字段指明每一个值从什么地方开始,在什么地方结束:
Name:S:0:11:Street:11:19:City:S:36:10:ZipCode:S:46:5:Country:S:51:6
这种方式给了程序员足够的灵活性来保存任何类型的数据,但在其他程序中使用这些数据会变得非常困难。当然,你可以编写自定义的解析代码,但这过程依赖于你的数据量和数据类型,过程可能非常枯燥和冗长。
这种私有的数据格式,在其他程序比如 Word 中就无法创建客户列表了,也不可能执行查询来过滤这些用户配置数据或排序,你更不能通过查询来获得指定城市中的所有用户。不过,解决方案有两种:
- 使用自定义数据组件代替用户配置,在数据库中存储和获取数据
- 创建一个自定义的用户配置提供程序,以使用你的数据库架构来存储信息
方案二仍允许你的页面使用用户配置模型。实际上,你可以创建一个使用 SQLProfileProvider 的标准用户配置序列化方案,之后再将其切换成自定义的提供程序。整个切换无需修改任何代码,只需修改 web.config 配置。
3. 用户配置和验证
用户配置和自定义的数据组件很自然会被放在一起比较。很明显,数据组件更加灵活。不仅可以维护用户信息、存储其他类型的信息、并执行更加复杂的任务。
ASP.NET 提供的标准用户配置提供程序(SQLProfileProvider )没有提供太多额外的功能。下面的列表是自定义数据组件可以很容易添加的功能,但 SQLProfileProvider 中是没有的。如果你需要其中任意功能,就得放弃用户配置,或者你需要创建一个自定义的用户配置程序:
- 加密:用户配置数据可以被序列化为字符串、XML或者二进制,但它仍然是原始的文本数据。如果有敏感信息,你唯一的选择是加密之后再进行存储,这导致你必须在你的代码中放入加密逻辑,这会是你不希望发生的
- 验证:你无法限制用户配置里存储的信息类型。你需要使用其他工具(例如验证控件或自定义的数据类)防止无效数据
- 缓存:你不能将从数据库取出的信息保存在内存中,虽然可以复制到缓存中,但跟踪这些信息会非常困难
- 审核:设计一个自定义数据组件时,你可以添加任何登录或者跟踪代码。可以使用这种方式诊断意外的错误或者监控 Web 程序的性能。如果你想在用户配置里使用这种功能,你需要创建一个自定义的用户配置程序,并在其中包含登录代码