Community Server专题八:MemberRole之Membership深入篇 [转]

专题八的上篇大致讨论了MemberRole中的Membership实现,对于运用Membership进行web开发足够,但是对于想更深入了解Membership实现机理的朋友那是远远不够的,这个专题我们更深入一下了解Membership。
None.gif其实MemberRole是一个非常好的资源包,借住Reflector这个优秀的工具,你可以对其进行代码分析。它无论是在组建的构架、代码的设计、数据库表的建立、存储过程的使用等都是非常优秀的,你是程序员也好构架师也罢,其中可以学习的真的很多很多,我在整个分析的过程中也深深受益。
None.gif由于MemberRole中的Membership只实现了对SQL Server的操Provider类,即SqlMembershipProvider类。因此我们从SqlMembershipProvider开始分析。Provider模型在上篇已经做过介绍,SqlMembershipProvider类继承了MembershipProvider,并实现其所有的抽象方法。在分析之前先看两个类:MembershipUser与MembershipUserCollection。
None.gifMembershipUser,先看看代码:(代码中省略的具体实现,只有方法与属性名称)
None.gif
public   class  MembershipUser
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      
// Methods
InBlock.gif
      protected MembershipUser();
InBlock.gif      
public MembershipUser(MembershipProvider provider, string name, object providerUserKey, string email, string passwordQuestion, string comment, bool isApproved, bool isLockedOut, DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate, DateTime lastPasswordChangedDate, DateTime lastLockoutDate);
InBlock.gif      
public virtual bool ChangePassword(string oldPassword, string newPassword);
InBlock.gif      
public virtual bool ChangePasswordQuestionAndAnswer(string password, string newPasswordQuestion, string newPasswordAnswer);
InBlock.gif      
public virtual string GetPassword();
InBlock.gif      
public virtual string GetPassword(string passwordAnswer);
InBlock.gif      
public virtual string ResetPassword();
InBlock.gif      
public virtual string ResetPassword(string passwordAnswer);
InBlock.gif      
public override string ToString();
InBlock.gif      
public virtual bool UnlockUser();
InBlock.gif      
internal virtual void Update();
InBlock.gif      
private void UpdateSelf();
InBlock.gif      
// Properties
ExpandedSubBlockStart.gifContractedSubBlock.gif
      public virtual string Comment dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual DateTime CreationDate dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual string Email dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual bool IsApproved dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual bool IsLockedOut dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public bool IsOnline dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual DateTime LastActivityDate dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual DateTime LastLockoutDate dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual DateTime LastLoginDate dot.gifgetset; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual DateTime LastPasswordChangedDate dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual string PasswordQuestion dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual MembershipProvider Provider dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual object ProviderUserKey dot.gifget; }
ExpandedSubBlockStart.gifContractedSubBlock.gif      
public virtual string UserName dot.gifget; }
InBlock.gif      
// Fields
InBlock.gif
      private string _Comment;
InBlock.gif      
private DateTime _CreationDate;
InBlock.gif      
private string _Email;
InBlock.gif      
private bool _IsApproved;
InBlock.gif      
private bool _IsLockedOut;
InBlock.gif      
private DateTime _LastActivityDate;
InBlock.gif      
private DateTime _LastLockoutDate;
InBlock.gif      
private DateTime _LastLoginDate;
InBlock.gif      
private DateTime _LastPasswordChangedDate;
InBlock.gif      
private string _PasswordQuestion;
InBlock.gif      
private MembershipProvider _Provider;
InBlock.gif      
private object _ProviderUserKey;
InBlock.gif      
private string _UserName;
ExpandedBlockEnd.gif}

None.gif这是一个实体类,表示一个由Membership创建的User,该类中有这个User的一些基本状态,如该User的UserName、Email等,还有一些方法,如ChangePassword()、ResetPassword()等(如果你是初学者,还在为建立一个对象需要什么属性,包含什么方法发愁,那这就是你应该好好学的,这也是OOP最基本的要求)。
None.gifMembershipUserCollection,这是一个MembershipUser类的容器,用来存放MembershipUser列表,记得上次广州.net俱乐部聚会时,我的演讲中有朋友在提出CS是否使用自定义类来存储用户列表,其实在这里可以看到CS中使用的就是自定义的类而不是DataSet(我想在asp.net 
2 .0正式发布后这也不会改变),这样做主要是因为考虑到性能与灵活性。
None.gif好了,回到SqlMembershipProvider类上来,我们具体分析一个有代表性质的方法:
None.gif
public   override  MembershipUser CreateUser( string  username,  string  password,  string  email,  string  passwordQuestion,  string  passwordAnswer,  bool  isApproved,  object  providerUserKey,  out  MembershipCreateStatus status)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif      
string text3;
InBlock.gif      MembershipUser user1;
InBlock.gif      
if (!SecUtility.ValidateParameter(ref password, truetruefalse0x80))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
string text1 = base.GenerateSalt();
InBlock.gif      
string text2 = base.EncodePassword(password, (intthis._PasswordFormat, text1);
InBlock.gif      
if (text2.Length > 0x80)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (passwordAnswer != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            passwordAnswer 
= passwordAnswer.Trim();
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if ((passwordAnswer != null&& (passwordAnswer.Length > 0))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
if (passwordAnswer.Length > 0x80)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  status 
= MembershipCreateStatus.InvalidAnswer;
InBlock.gif                  
return null;
ExpandedSubBlockEnd.gif            }

InBlock.gif            text3 
= base.EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), (intthis._PasswordFormat, text1);
ExpandedSubBlockEnd.gif      }

InBlock.gif      
else
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            text3 
= passwordAnswer;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (!SecUtility.ValidateParameter(ref text3, this.RequiresQuestionAndAnswer, this.RequiresQuestionAndAnswer, false0x80))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidAnswer;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (!SecUtility.ValidateParameter(ref username, truetruetrue0x100))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidUserName;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (!SecUtility.ValidateParameter(ref email, this.RequiresUniqueEmail, this.RequiresUniqueEmail, false0x100))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidEmail;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (!SecUtility.ValidateParameter(ref passwordQuestion, this.RequiresQuestionAndAnswer, this.RequiresQuestionAndAnswer, false0x100))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidQuestion;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if ((providerUserKey != null&& !(providerUserKey is Guid))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidProviderUserKey;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (password.Length < this.MinRequiredPasswordLength)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
int num1 = 0;
InBlock.gif      
for (int num2 = 0; num2 < password.Length; num2++)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
if (!char.IsLetterOrDigit(password, num2))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  num1
++;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif      }

InBlock.gif      
if (num1 < this.MinRequiredNonAlphanumericCharacters)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
if ((this.PasswordStrengthRegularExpression.Length > 0&& !Regex.IsMatch(password, this.PasswordStrengthRegularExpression))
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      ValidatePasswordEventArgs args1 
= new ValidatePasswordEventArgs(username, password, true);
InBlock.gif      
this.OnValidatingPassword(args1);
InBlock.gif      
if (args1.Cancel)
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            status 
= MembershipCreateStatus.InvalidPassword;
InBlock.gif            
return null;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
try
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            SqlConnectionHolder holder1 
= null;
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  holder1 
= SqlConnectionHelper.GetConnection(this._sqlConnectionString, true);
InBlock.gif                  
this.CheckSchemaVersion(holder1.Connection);
InBlock.gif                  SqlCommand command1 
= new SqlCommand("dbo.aspnet_Membership_CreateUser", holder1.Connection);
InBlock.gif                  command1.CommandTimeout 
= this.CommandTimeout;
InBlock.gif                  command1.CommandType 
= CommandType.StoredProcedure;
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, this.ApplicationName));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@UserName", SqlDbType.NVarChar, username));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@Password", SqlDbType.NVarChar, text2));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, text1));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@Email", SqlDbType.NVarChar, email));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@PasswordQuestion", SqlDbType.NVarChar, passwordQuestion));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@PasswordAnswer", SqlDbType.NVarChar, text3));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@IsApproved", SqlDbType.Bit, isApproved));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@UniqueEmail", SqlDbType.Int, this.RequiresUniqueEmail ? 1 : 0));
InBlock.gif                  command1.Parameters.Add(
this.CreateInputParam("@PasswordFormat", SqlDbType.Int, (intthis.PasswordFormat));
InBlock.gif                  command1.Parameters.Add(
this.GetTimeZoneAdjustmentParam());
InBlock.gif                  SqlParameter parameter1 
= this.CreateInputParam("@UserId", SqlDbType.UniqueIdentifier, providerUserKey);
InBlock.gif                  parameter1.Direction 
= ParameterDirection.InputOutput;
InBlock.gif                  command1.Parameters.Add(parameter1);
InBlock.gif                  parameter1 
= new SqlParameter("@ReturnValue", SqlDbType.Int);
InBlock.gif                  parameter1.Direction 
= ParameterDirection.ReturnValue;
InBlock.gif                  command1.Parameters.Add(parameter1);
InBlock.gif                  
object obj1 = command1.ExecuteScalar();
InBlock.gif                  DateTime time1 
= this.RoundToSeconds(DateTime.Now);
InBlock.gif                  
if ((obj1 != null&& (obj1 is DateTime))
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        time1 
= (DateTime) obj1;
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  
int num3 = (parameter1.Value != null? ((int) parameter1.Value) : -1;
InBlock.gif                  
if ((num3 < 0|| (num3 > 11))
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        num3 
= 11;
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  status 
= (MembershipCreateStatus) num3;
InBlock.gif                  
if (num3 != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        
return null;
ExpandedSubBlockEnd.gif                  }

InBlock.gif                  providerUserKey 
= new Guid(command1.Parameters["@UserId"].Value.ToString());
InBlock.gif                  
return new MembershipUser(this, username, providerUserKey, email, passwordQuestion, null, isApproved, false, time1, time1, time1, time1, new DateTime(0x6da11));
ExpandedSubBlockEnd.gif            }

InBlock.gif            
finally
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                  
if (holder1 != null)
ExpandedSubBlockStart.gifContractedSubBlock.gif                  
dot.gif{
InBlock.gif                        holder1.Close();
InBlock.gif                        holder1 
= null;
ExpandedSubBlockEnd.gif                  }

ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif      }

InBlock.gif      
catch
ExpandedSubBlockStart.gifContractedSubBlock.gif      
dot.gif{
InBlock.gif            
throw;
ExpandedSubBlockEnd.gif      }

InBlock.gif      
return user1;
ExpandedBlockEnd.gif}

None.gif该方法实现建立一个用户的过程,建立后返回一个被建立的MembershipUser对象,如果建立失败MembershipUser对象为null(其实我早期做过一些项目的时候喜欢在建立对象成功后返回一个ID)。可以看到在这个方法中有很多的if语句,它们是为了检验数据是否合法,这是必须的吗?其实不是,但对于构建一个强壮的底层代码这是必须的,不然一点点的错误都有可能导致系统的瘫痪。其实做项目与做开发有的时候不太一样,企业的有些项目开发很多时候只要能实现功能就可以了,而且开发过程也集中在一些现有的代码或者组建的基础上,个人的错误不会影响全局的运行,PM也不做过多要求。但如果是做产品,这个情况可能会有所改变,很多时候要求很严格,至少我是这样。在做完对输入参数的验证后,CreateUser建立与数据库的连接,这里是调用SqlConnectionHelper类下的GetConnection方法进行的,为了照顾初学者阅读,我这里讲一下为什么需要把对数据库连接与操作写在SqlConnectionHelper类下,而不是直接采用SqlConnection提供的方法,其实这是一个设计模式的问题,Membership的实现需要很多的方法与数据库进行交换数据库,如果每次方法都调用一次SqlConnection的方法建立数据库连接,一来会造成大量的代码冗余,而且一旦数据库连接语句一旦改变,你就要去修改很多个方法,如果你把这个过程都包装在一个类下面,连接数据库就有统一的入口,一来容易维护,二来不会有太多的代码冗余,再者如果需要查找错误也非常容易。这里Membership采用的是存储过程,我们可以看到使用的是dbo.aspnet_Membership_CreateUser存储过程,好了,打开你的数据库,找到这个存储过程:
None.gifCREATE PROCEDURE dbo.aspnet_Membership_CreateUser
None.gif    @ApplicationName                        NVARCHAR(
256 ),
None.gif    @UserName                               NVARCHAR(
256 ),
None.gif    @Password                               NVARCHAR(
128 ),
None.gif    @PasswordSalt                           NVARCHAR(
128 ),
None.gif    @Email                                  NVARCHAR(
256 ),
None.gif    @PasswordQuestion                       NVARCHAR(
256 ),
None.gif    @PasswordAnswer                         NVARCHAR(
128 ),
None.gif    @IsApproved                             BIT,
None.gif    @TimeZoneAdjustment                     INT,
None.gif    @CreateDate                             DATETIME 
=  NULL,
None.gif    @UniqueEmail                            INT      
=   0 ,
None.gif    @PasswordFormat                         INT      
=   0 ,
None.gif    @UserId                                 UNIQUEIDENTIFIER OUTPUT
None.gifAS
None.gifBEGIN
None.gif    DECLARE @ApplicationId UNIQUEIDENTIFIER
None.gif    SELECT  @ApplicationId 
=  NULL
None.gif
None.gif    DECLARE @NewUserId UNIQUEIDENTIFIER
None.gif    SELECT @NewUserId 
=  NULL
None.gif
None.gif    DECLARE @IsLockedOut BIT
None.gif    SET @IsLockedOut 
=   0
None.gif
None.gif    DECLARE @LastLockoutDate  DATETIME
None.gif    SET @LastLockoutDate 
=  CONVERT( DATETIME,  ' 17540101 ' 112  )
None.gif
None.gif    DECLARE @FailedPasswordAttemptCount INT
None.gif    SET @FailedPasswordAttemptCount 
=   0
None.gif
None.gif    DECLARE @FailedPasswordAttemptWindowStart  DATETIME
None.gif    SET @FailedPasswordAttemptWindowStart 
=  CONVERT( DATETIME,  ' 17540101 ' 112  )
None.gif
None.gif    DECLARE @FailedPasswordAnswerAttemptCount INT
None.gif    SET @FailedPasswordAnswerAttemptCount 
=   0
None.gif
None.gif    DECLARE @FailedPasswordAnswerAttemptWindowStart  DATETIME
None.gif    SET @FailedPasswordAnswerAttemptWindowStart 
=  CONVERT( DATETIME,  ' 17540101 ' 112  )
None.gif
None.gif    DECLARE @NewUserCreated BIT
None.gif    DECLARE @ReturnValue   INT
None.gif    SET @ReturnValue 
=   0
None.gif
None.gif    DECLARE @ErrorCode     INT
None.gif    SET @ErrorCode 
=   0
None.gif
None.gif    DECLARE @TranStarted   BIT
None.gif    SET @TranStarted 
=   0
None.gif
None.gif    IF( @@TRANCOUNT 
=   0  )
None.gif    BEGIN
None.gif        BEGIN TRANSACTION
None.gif        SET @TranStarted 
=   1
None.gif    END
None.gif    ELSE
None.gif        SET @TranStarted 
=   0
None.gif
None.gif    EXEC dbo.aspnet_Applications_CreateApplication @ApplicationName, @ApplicationId OUTPUT
None.gif
None.gif    IF( @@ERROR 
<>   0  )
None.gif    BEGIN
None.gif        SET @ErrorCode 
=   - 1
None.gif        GOTO Cleanup
None.gif    END
None.gif
None.gif    IF (@CreateDate IS NULL)
None.gif        EXEC dbo.aspnet_GetUtcDate @TimeZoneAdjustment, @CreateDate OUTPUT
None.gif    ELSE
None.gif        SELECT  @CreateDate 
=  DATEADD(n,  - @TimeZoneAdjustment, @CreateDate)  --   switch  TO UTC time
None.gif
None.gif    SELECT  @NewUserId 
=  UserId FROM dbo.aspnet_Users WHERE LOWER(@UserName)  =  LoweredUserName AND @ApplicationId  =  ApplicationId
None.gif    IF ( @NewUserId IS NULL )
None.gif    BEGIN
None.gif        SET @NewUserId 
=  @UserId
None.gif        EXEC @ReturnValue 
=  dbo.aspnet_Users_CreateUser @ApplicationId, @UserName,  0 , @CreateDate, @NewUserId OUTPUT
None.gif        SET @NewUserCreated 
=   1
None.gif    END
None.gif    ELSE
None.gif    BEGIN
None.gif        SET @NewUserCreated 
=   0
None.gif        IF( @NewUserId 
<>  @UserId AND @UserId IS NOT NULL )
None.gif        BEGIN
None.gif            SET @ErrorCode 
=   6
None.gif            GOTO Cleanup
None.gif        END
None.gif    END
None.gif
None.gif    IF( @@ERROR 
<>   0  )
None.gif    BEGIN
None.gif        SET @ErrorCode 
=   - 1
None.gif        GOTO Cleanup
None.gif    END
None.gif
None.gif    IF( @ReturnValue 
=   - 1  )
None.gif    BEGIN
None.gif        SET @ErrorCode 
=   10
None.gif        GOTO Cleanup
None.gif    END
None.gif
None.gif    IF ( EXISTS ( SELECT UserId
None.gif                  FROM   dbo.aspnet_Membership
None.gif                  WHERE  @NewUserId 
=  UserId ) )
None.gif    BEGIN
None.gif        SET @ErrorCode 
=   6
None.gif        GOTO Cleanup
None.gif    END
None.gif
None.gif    SET @UserId 
=  @NewUserId
None.gif
None.gif    IF (@UniqueEmail 
=   1 )
None.gif    BEGIN
None.gif        IF (EXISTS (SELECT 
*
None.gif                    FROM  dbo.aspnet_Membership m WITH ( UPDLOCK, HOLDLOCK )
None.gif                    WHERE ApplicationId 
=  @ApplicationId AND LoweredEmail  =  LOWER(@Email)))
None.gif        BEGIN
None.gif            SET @ErrorCode 
=   7
None.gif            GOTO Cleanup
None.gif        END
None.gif    END
None.gif
None.gif    INSERT INTO dbo.aspnet_Membership
None.gif                ( ApplicationId,
None.gif                  UserId,
None.gif                  Password,
None.gif                  PasswordSalt,
None.gif                  Email,
None.gif                  LoweredEmail,
None.gif                  PasswordQuestion,
None.gif                  PasswordAnswer,
None.gif                  PasswordFormat,
None.gif                  IsApproved,
None.gif                  IsLockedOut,
None.gif                  CreateDate,
None.gif                  LastLoginDate,
None.gif                  LastPasswordChangedDate,
None.gif                  LastLockoutDate,
None.gif                  FailedPasswordAttemptCount,
None.gif                  FailedPasswordAttemptWindowStart,
None.gif                  FailedPasswordAnswerAttemptCount,
None.gif                  FailedPasswordAnswerAttemptWindowStart )
None.gif         VALUES ( @ApplicationId,
None.gif                  @UserId,
None.gif                  @Password,
None.gif                  @PasswordSalt,
None.gif                  @Email,
None.gif                  LOWER(@Email),
None.gif                  @PasswordQuestion,
None.gif                  @PasswordAnswer,
None.gif                  @PasswordFormat,
None.gif                  @IsApproved,
None.gif                  @IsLockedOut,
None.gif                  @CreateDate,
None.gif                  @CreateDate,
None.gif                  @CreateDate,
None.gif                  @LastLockoutDate,
None.gif                  @FailedPasswordAttemptCount,
None.gif                  @FailedPasswordAttemptWindowStart,
None.gif                  @FailedPasswordAnswerAttemptCount,
None.gif                  @FailedPasswordAnswerAttemptWindowStart )
None.gif
None.gif    IF( @@ERROR 
<>   0  )
None.gif    BEGIN
None.gif        SET @ErrorCode 
=   - 1
None.gif        GOTO Cleanup
None.gif    END
None.gif
None.gif    IF (@NewUserCreated 
=   0 )
None.gif    BEGIN
None.gif        UPDATE dbo.aspnet_Users
None.gif        SET    LastActivityDate 
=  @CreateDate
None.gif        WHERE  @UserId 
=  UserId
None.gif        IF( @@ERROR 
<>   0  )
None.gif        BEGIN
None.gif            SET @ErrorCode 
=   - 1
None.gif            GOTO Cleanup
None.gif        END
None.gif    END
None.gif
None.gif    SELECT @CreateDate 
=  DATEADD( n, @TimeZoneAdjustment, @CreateDate )
None.gif
None.gif    IF( @TranStarted 
=   1  )
None.gif    BEGIN
None.gif        SET @TranStarted 
=   0
None.gif        COMMIT TRANSACTION
None.gif    END
None.gif
None.gif    RETURN 
0
None.gif
None.gifCleanup:
None.gif
None.gif    IF( @TranStarted 
=   1  )
None.gif    BEGIN
None.gif        SET @TranStarted 
=   0
None.gif        ROLLBACK TRANSACTION
None.gif    END
None.gif
None.gif    RETURN @ErrorCode
None.gif
None.gifEND
None.gif
None.gifGO
None.gif够长的,不过没有关系,分几个部分看,首先是定义一些要发挥得参数,然后初始化,接着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表,再下来还有一些对错误的处理dot.gif
None.gif其实这个存储过程并不复杂,但是非常繁琐的,也可以看出设计者对数据库检验的严格性的要求非常高。有了对存储过程一定的了解后,我们接下来那些传递的参数也就明白有何用处了,最后关闭数据库的连接,把返回的这些参数通过实例化一个MembershipUser类传递过去,然后返回这个实例化的MembershipUser,这样该方法就完成了一次操作。
None.gif最后我们看看数据库,Membership直接关联的有3个表
None.gif 
None.gif表很简单,关系也很明了,我就不多说了,总要给我留点时间吧,也给你自己留一些分析的空间,我要是全都说完了那你做什么?呵呵。
None.gif    如果你了解CS系统,你肯定会提出这样一个疑问:用户信息不只表Membership中这一点呀,保存用户个性化设置的如选用什么语言、什么皮肤等等信息的数据都在哪里?期待吧,那是后面的Profile专题需要叙述的问题

转载于:https://www.cnblogs.com/guodapeng/archive/2007/12/21/1009080.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值