AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > SQL Server

MemberRole之Membership深入篇

51自学网 http://www.wanshiok.com

 

  该方法实现建立一个用户的过程,建立后返回一个被建立的MembershipUser对象,如果建立失败MembershipUser对象为null(其实我早期做过一些项目的时候喜欢在建立对象成功后返回一个ID)。可以看到在这个方法中有很多的if语句,它们是为了检验数据是否合法,这是必须的吗?其实不是,但对于构建一个强壮的底层代码这是必须的,不然一点点的错误都有可能导致系统的瘫痪。其实做项目与做开发有的时候不太一样,企业的有些项目开发很多时候只要能实现功能就可以了,而且开发过程也集中在一些现有的代码或者组建的基础上,个人的错误不会影响全局的运行,PM也不做过多要求。但如果是做产品,这个情况可能会有所改变,很多时候要求很严格,至少我是这样。在做完对输入参数的验证后,CreateUser建立与数据库的连接,这里是调用SqlConnectionHelper类下的GetConnection方法进行的,为了照顾初学者阅读,我这里这一下为什么需要把对数据库连接与操作写在SqlConnectionHelper类下,而不是直接采用SqlConnection提供的方法,其实这是一个设计模式的问题,Membership的实现需要很多的方法与数据库进行交换数据库,如果每次方法都调用一次SqlConnection的方法建立数据库连接,一来会造成大量的代码冗余,而且一旦数据库连接语句一旦改变,你就要去修改很多个方法,如果你把这个过程都包装在一个类下面,连接数据库就有统一的入口,一来容易维护,二来不会有太多的代码冗余,再者如果需要查找错误也非常容易。这里Membership采用的是存储过程,我们可以看到使用的是dbo.aspnet_Membership_CreateUser存储过程,好了,打开你的数据库,找到这个存储过程:

CREATE PROCEDURE dbo.aspnet_Membership_CreateUser

@ApplicationName NVARCHAR(256),

@UserName NVARCHAR(256),

@Password NVARCHAR(128),

@PasswordSalt NVARCHAR(128),

@Email NVARCHAR(256),

@PasswordQuestion NVARCHAR(256),

@PasswordAnswer NVARCHAR(128),

@IsApproved BIT,

@TimeZoneAdjustment INT,

@CreateDate DATETIME = NULL,

@UniqueEmail INT = 0,

@PasswordFormat INT = 0,

@UserId UNIQUEIDENTIFIER OUTPUT

AS

BEGIN

DECLARE @ApplicationId UNIQUEIDENTIFIER

SELECT @ApplicationId = NULL

DECLARE @NewUserId UNIQUEIDENTIFIER

SELECT @NewUserId = NULL

DECLARE @IsLockedOut BIT

SET @IsLockedOut = 0

DECLARE @LastLockoutDate DATETIME

SET @LastLockoutDate = CONVERT( DATETIME, '17540101', 112 )

DECLARE @FailedPasswordAttemptCount INT

SET @FailedPasswordAttemptCount = 0

DECLARE @FailedPasswordAttemptWindowStart DATETIME

SET @FailedPasswordAttemptWindowStart = CONVERT( DATETIME, '17540101', 112 )

DECLARE @FailedPasswordAnswerAttemptCount INT

SET @FailedPasswordAnswerAttemptCount = 0

DECLARE @FailedPasswordAnswerAttemptWindowStart DATETIME

SET @FailedPasswordAnswerAttemptWindowStart = CONVERT( DATETIME, '17540101', 112 )

DECLARE @NewUserCreated BIT

DECLARE @ReturnValue INT

SET @ReturnValue = 0

DECLARE @ErrorCode INT

SET @ErrorCode = 0

DECLARE @TranStarted BIT

SET @TranStarted = 0

IF( @@TRANCOUNT = 0 )

BEGIN

BEGIN TRANSACTION

SET @TranStarted = 1

END

ELSE

SET @TranStarted = 0

EXEC dbo.aspnet_Applications_CreateApplication @ApplicationName, @ApplicationId OUTPUT

IF( @@ERROR <> 0 )

BEGIN

SET @ErrorCode = -1

GOTO Cleanup

END

IF (@CreateDate IS NULL)

EXEC dbo.aspnet_GetUtcDate @TimeZoneAdjustment, @CreateDate OUTPUT

ELSE

SELECT @CreateDate = DATEADD(n, -@TimeZoneAdjustment, @CreateDate) -- switch TO UTC time

SELECT @NewUserId = UserId FROM dbo.aspnet_Users WHERE LOWER(@UserName) = LoweredUserName AND @ApplicationId = ApplicationId

IF ( @NewUserId IS NULL )

BEGIN

SET @NewUserId = @UserId

EXEC @ReturnValue = dbo.aspnet_Users_CreateUser @ApplicationId, @UserName, 0, @CreateDate, @NewUserId OUTPUT

SET @NewUserCreated = 1

END

ELSE

BEGIN

SET @NewUserCreated = 0

IF( @NewUserId <> @UserId AND @UserId IS NOT NULL )

BEGIN

SET @ErrorCode = 6

GOTO Cleanup

END

END

IF( @@ERROR <> 0 )

BEGIN

SET @ErrorCode = -1

GOTO Cleanup

END

IF( @ReturnValue = -1 )

BEGIN

SET @ErrorCode = 10

GOTO Cleanup

END

IF ( EXISTS ( SELECT UserId

FROM dbo.aspnet_Membership

WHERE @NewUserId = UserId ) )

BEGIN

SET @ErrorCode = 6

GOTO Cleanup

END

SET @UserId = @NewUserId

IF (@UniqueEmail = 1)

BEGIN

IF (EXISTS (SELECT *

FROM dbo.aspnet_Membership m WITH ( UPDLOCK, HOLDLOCK )

WHERE ApplicationId = @ApplicationId AND LoweredEmail = LOWER(@Email)))

BEGIN

SET @ErrorCode = 7

GOTO Cleanup

END

END

INSERT INTO dbo.aspnet_Membership

( ApplicationId,

UserId,

Password,

PasswordSalt,

Email,

LoweredEmail,

PasswordQuestion,

PasswordAnswer,

PasswordFormat,

IsApproved,

IsLockedOut,

CreateDate,

LastLoginDate,

LastPasswordChangedDate,

LastLockoutDate,

FailedPasswordAttemptCount,

FailedPasswordAttemptWindowStart,

FailedPasswordAnswerAttemptCount,

FailedPasswordAnswerAttemptWindowStart )

VALUES ( @ApplicationId,

@UserId,

@Password,

@PasswordSalt,

@Email,

LOWER(@Email),

@PasswordQuestion,

@PasswordAnswer,

@PasswordFormat,

@IsApproved,

@IsLockedOut,

@CreateDate,

@CreateDate,

@CreateDate,

@LastLockoutDate,

@FailedPasswordAttemptCount,

@FailedPasswordAttemptWindowStart,

@FailedPasswordAnswerAttemptCount,

@FailedPasswordAnswerAttemptWindowStart )

IF( @@ERROR <> 0 )

BEGIN

SET @ErrorCode = -1

GOTO Cleanup

END

IF (@NewUserCreated = 0)

BEGIN

UPDATE dbo.aspnet_Users

SET LastActivityDate = @CreateDate

WHERE @UserId = UserId

IF( @@ERROR <> 0 )

BEGIN

SET @ErrorCode = -1

GOTO Cleanup

END

END

SELECT @CreateDate = DATEADD( n, @TimeZoneAdjustment, @CreateDate )

IF( @TranStarted = 1 )

BEGIN

SET @TranStarted = 0

COMMIT TRANSACTION

END

RETURN 0

Cleanup:

IF( @TranStarted = 1 )

BEGIN

SET @TranStarted = 0

ROLLBACK TRANSACTION

END

RETURN @ErrorCode

END

GO


  够长的,不过没有关系,分几个部分看,首先是定义一些要发挥得参数,然后初始化,接着EXEC dbo.aspnet_Applications_CreateApplication,调用aspnet_Applications_CreateApplication存储过程,建立一个名字为@ApplicationName 的Application,如果该Application不存在的话.并且返回该Application的ID,这里的ApplicationName在web.config membership节点中设置过,即:dev。如果执行以上过程有错误,通过SQL的GOTO语句跳至Cleanup部分,执行ROLLBACK TRANSACTION,回滚这次操作。如果没有错误存储过程就接着向下执行,EXEC dbo.aspnet_GetUtcDate @TimeZoneAdjustment, @CreateDate OUTPUT,这是获得当前Utc时间。再下来就判断aspnet_Users表中用户的UserId是否在数据库中有该UserId(UserId是一个Guid),如果没有就在表aspnet_Users中建立。这时在进行一次失分发生错误的判断,执行的方法与前一次一样。再下来判断aspnet_Membership表中是否有该UserId存在,如果没有就根据@UniqueEmail参数判断是否允许Email在数据库中重复。最后才是把User的信息插入aspnet_Membership表,再下来还有一些对错误的处理...

  其实这个存储过程并不复杂,但是非常繁琐的,也可以看出设计者对数据库检验的严格性的要求非常高。有了对存储过程一定的了解后,我们接下来那些传递的参数也就明白有何用处了,最后关闭数据库的连接,把返回的这些参数通过实例化一个MembershipUser类传递过去,然后返回这个实例化的MembershipUser,这样该方法就完成了一次操作。

  最后我们看看数据库,Membership直接关联的有3个表

  表很简单,关系也很明了,我就不多说了,总要给我留点时间吧,也给你自己留一些分析的空间,我要是全都说完了那你做什么?呵呵。

  如果你了解CS系统,你肯定会提出这样一个疑问:用户信息不只表Membership中这一点呀,保存用户个性化设置的如选用什么语言、什么皮肤等等信息的数据都在哪里?期待吧,那是后面的Profile专题需要叙述的问题。

 
 

上一篇:将DataGrid数据写入Excel文件  下一篇:浅谈SQL&nbsp;Server数据类型最大值