本文英文原版及代码下载:
http://aspnet.4guysfromrolla.com/articles/091207-1.aspx
考察ASP.NET 2.0的Membership, Roles和Profile - Part 9
导言:
ASP.NET 2.0的Membership, Roles和Profile系统设计成使用provider模式。ASP.NET使用一个provider在SQL Server或Active Directory里对进行members 和 roles信息进行管理。另外我们还可以从微软下载其它的providers,将membership 和 role信息存储在一个Microsoft Access数据库里(见Part 8部分).本系列的大部分文章将焦点放在SQL Server provider(比如SqlMembershipProvider, SqlRoleProvider,和SqlProfileProvider)上,诚然,对基于Internet的web应用程序而言, SQL Server providers是上佳之选,但如果是企业内部网(intranet)的话,使用Active Directory provider要更常见一些.
这些SQL Server provider在指定的SQL Server数据库里创建一系列的表、视图和存储过程,因此当使用这些provider时,我们可以通过T-SQL statements对membership 或 roles 或 profile相关的信息进行添加、修改、或删除.在本文我们将看到常见的membership操作——删除users.当然,我们可以通过Membership API来进行删除,不过在某些时候使用一个T-SQL脚本或许更简单些.然而,如果绕开managed APIs而直接处理数据库将面临一些挑战。在本文我们将阐述这些问题,探讨用T-SQL替代managed APIs的优缺点。我们将同时考察使用managed API方法和T-SQL命令来删除某个用户和所有用户的情况.
考量使用API还是直接处理SQL Server
SQL Server provider将在一个指定的SQL Server数据库里创建Membership, Roles, 和 Profile系统所必需的表、试图、存储过程等.当使用 ASP.NET Website管理工具的时候,这些数据库对象将自动创建在ASPNETDB.MDF数据库里,它位于 ~/App_Data文件夹里.另外,我们还可以通过ASP.NET SQL Server注册工具 (aspnet_regsql.exe) (见Part 3),来显式地创建这些对象.
.NET的Membership, Roles, 和 Profile系统的API提供了一系列的方法来创建、修改、删除用户帐号.然而,SQL Server provider直接通过T-SQL command而不是"编码"来修改、添加、删除用户帐户.这些API方法调用可用的存储过程.要是绕开这些API和存储过程,手动修改这些表数据的话有可能导致数据出错.比如,在Membership表里存储有每个用户的密码,如果这些密码经过了哈希算法处理,错误地修改这些密码将导致锁定(lock out)用户,因为用户登录时提供的密码与存储在数据库里的密码不匹配.简而言之,如果你决定直接从T-SQL commands处理用户信息的话,最好是使用provider提供的存储过程。另外,务必对你调用的存储过程和数据模式(data model)有一个清醒的认识.
使用托管API(managed API)相对于直接对数据库进行修改有几点优势。比如,托管API比基于SQL Server的provider的存储过程和数据模式易于理解.Membership, Roles,和 Profile API包含的方法和属性的信息都在微软的官方网站进行的很好的归档处理。对属性、方法、参数名我们都可以通过其名称以及描述很容易就理解了.而SQL Server存储过程的文档资料就比较少了.
托管API的缺点在于你必须写代码来执行.典型的情况是,这些代码将放置在网站的某些管理模块的一个web页面上,要求用户登录,访问该管理模块,再执行必要的命令(比如从数据库删除某个用户或删除所有的用户)。使用T-SQL commands的优点在于更容易地进行调用。假设你有一个用于测试的服务,并手动添加了一些帐户,当软件升级了后,你打算删除所有的帐户数据并创建新的测试帐户,为此,我们可以执行一个T-SQL脚本来完成.该脚本用恰当的命令来删除当前用户并添加新的测试用户.
本文的剩余部分将考察如何删除一个用户和所有用户,同时用托管API和T-SQL command两种方法.
删除单个用户
要用托管API来删除单个用户,可以使用Membership.DeleteUser(username[, deleteAllData]方法.该方法至少要提供一个字符串输入参数——也就是要删除的用户的username.另外,还有一个可选的布尔值参数,它决定是否删除所有相关的用户信息——比如role信息, profile数据等等.如果你没有显式的提供该布尔值,那么将使用True值.对SQL Server provider而言,该Membership.DeleteUser方法将调用存储过程_Users_DeleteUser,它接受如下的参数:
.@ApplicationName——找到某个user并将其删除的那个应用程序.正如我们在 Part 1探讨的那样,membership system根据不同的应用程序名称进行划分,以便多个web应用程序使用共同的member store.
.@UserName——要删除的用户的名称
.@TablesToDeleteFrom——它为整型的值,用于指明从哪些与membership相关的表删除数据.其参数为比特类型(bit field),如果你输入的值为1,那么仅仅从表aspnet_Membership删除数据;而并不会从表aspnet_Users删除用户。如果你调用Membership.DeleteUser(username, False)方法, 那么将会将值1传递给该参数.如果为该参数传递其它值,将使存储过程从其它表删除记录.当传递的值为15(也就是说调用 Membership.DeleteUser(username) 或 Membership.DeleteUser(username, True)方法时传递的值)时,将从与用户帐户相关的表删除所有与user相关的记录,包括aspnet_Users表.简而言之,当传递的值为15时,将把user从数据库全部删除.
.@NumTablesDeletedFrom——一个输出参数,返回删除数据的表的数量.
本文下载资料里包含了一个web页面,允许登录者查看列出来的所有用户,他可以选择一个用户,点击一个按钮并调用Membership.DeleteUser(username)方法将其删除.
图1
要通过T-SQL删除某个特定的用户,仅仅需要调用存储过程aspnet_Users_DeleteUser,并传入相应的参数即可:
DECLARE @NumTablesDeletedFrom int
EXEC aspnet_Users_DeleteUser applicationName, userName, 15, @NumTablesDeletedFrom OUTPUT
PRINT 'Number of tables deleted from: ' + @NumTablesDeletedFrom
要确定应用程序的名称,可以查看表aspnet_Applications.正如在Part 1 探讨的那样,我们可以通过Web.config文件明确的指定应用程序的名称.更详细的阐述请参阅文章《Always Set the "applicationName" Property When Configuring ASP.NET 2.0 Membership and Other Providers》(http://weblogs.asp.net/scottgu/archive/2006/04/22/Always-set-the-_2200_applicationName_2200_-property-when-configuring-ASP.NET-2.0-Membership-and-other-Providers.aspx).
删除所有的User
Membership API并不包含删除所有用户的Membership.DeleteAllUsers()方法,同样SQL Server provider也没有包含一个存储过程来删除所有的用户.不过稍加修改,我们就可以自己实现该功能.Membership API有一个获取所有系统用户的Membership.GetAllUsers方法.我们可以用该方法获取所有用户的一个列表,再遍历这些用户,对每个用户调用 Membership.DeleteUser(username)方法.
' Visual Basic
'Enumerate each user and delete him!
For Each usr As MembershipUser In Membership.GetAllUsers()
Membership.DeleteUser(usr.UserName)
Next
// C#
foreach (MembershipUser usr in Membership.GetAllUsers())
Membership.DeleteUser(usr.UserName);
类似的,我们可以通过T-SQL命令来删除所有的用户.你可以创建一个指针(CURSOR),用户列举aspnet_Users表里的用户,再对每一条记录调用存储过程aspnet_Users_DeleteUser。关于指针的更多信息请参阅文章《Using SQL Server Cursors》(http://www.databasejournal.com/features/mssql/article.php/1439731)
还有一个更简单的方法:从相应的表删除所有的记录.唯一的问题是在这些相关的表之间存在外键约束(foreign key constraint),所以你要确保在删除"父表"的数据之前先删除"子表"的数据.下面的DELETE命令按照正确的顺序进行操作:
DELETE FROM dbo.aspnet_Membership
DELETE FROM dbo.aspnet_UsersInRoles
DELETE FROM dbo.aspnet_Profile
DELETE FROM dbo.aspnet_PersonalizationPerUser
DELETE FROM aspnet_Users
最后还有一个办法,通过删除member store来删除所有的用户,方法是通过运行aspnet_regsql.exe来重新构建SQL Server provider数据库对象.
祝编程愉快!