Duwamish7分析——帐户管理

“Account Details”(帐户明细)页显示用户的帐户信息,还允许用户修改帐户信息。但是,在可以修改信息前,用户必须首先通过登录过程登录和创建帐户。任何已经创建帐户的用户都可以返回到“Logon”(登录)页,键入凭据,然后前进到“Account Details”页修改帐户信息。有关登录过程的更多信息,请参见登录。
实现
“Account Details”(帐户明细)页使用下面的 ASP.NET 文件和 C# 或 Visual Basic .NET 代码隐藏文件:
Account.aspx
Account.aspx.cs
Account.aspx.vb
注意   有关 ASP.NET 代码隐藏的更多信息,请参见创建 ASP.NET Web 应用程序。
创建新帐户的序列关系图

过程概述
在 Web 层启动帐户管理过程。当加载页时,通过 Web 层的 Duwamish7.Web.Account.SubmitButton_Click 方法和 Duwamish7.Web.AccountModule.ProcessChanges 方法更新用户的帐户信息。然后,Web 方法调用业务外观的 Duwamish7.BusinessFacade.CustomerSystem.UpdateCustomer 方法,该方法创建密码的经过 salt 和散列运算的新表示形式,然后使用业务规则层的 Duwamish7.BusinessRules.Customer.Update 方法。下一步,调用数据访问层的 Duwamish7.DataAccess.Customers.UpdateCustomer 方法,而此方法又调用数据库层中的 UpdateCustomer 存储过程。
如果用户创建新帐户,则 Web 层的 Duwamish7.Web.Secure.Logon.SubmitButton_Click 方法向 Duwamish 7.0 应用程序的数据库提供用户帐户信息。Duwamish7.Web.Secure.Logon.SubmitButton_Click 方法调用 Duwamish7.Web.AccountModule.ProcessChanges 方法,而后者调用业务外观层的 Duwamish7.BusinessFacade.CustomerSystem.CreateCustomer 方法。Duwamish7.BusinessFacade.CustomerSystem.CreateCustomer 方法为用户创建密码的经过 salt 和散列运算的表示形式,然后调用业务规则层的 Duwamish7.BusinessRules.Customer.Insert 方法。如果新用户尝试使用数据库内已有的电子邮件地址,则应用程序通知用户电子邮件地址已在使用中。用户必须提交数据库内尚没有的另一个电子邮件地址。假定用户提交唯一的电子邮件地址,Duwamish7.BusinessRules.Customer.Insert 方法调用数据访问层的 Duwamish7.DataAccess.Customers.InsertCustomer 方法。然后 Duwamish7.DataAccess.Customers.InsertCustomer 方法调用数据库层的 InsertCustomer 存储过程,后者在数据库内创建新的客户帐户。
要点
帐户管理是使用业务规则层的少数几个地方之一。
新帐户的数据创建和现有帐户的数据修改是相同的。因此,Duwamish 7.0 使用一个名为 AccountModule 的用户控件来处理这两个过程。有关 ASP.NET 用户控件的进一步信息,请参见 UserControl 类。
若要查找适用于本主题中特定层的源代码,请单击相应的链接:
业务外观源代码 | 业务规则源代码 | 数据访问源代码 | SPROC
Web 源代码
Duwamish7.Web.Account.SubmitButton_Click 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Web/Secure/Account.aspx.cs 文件。Duwamish7.Web.AccountModule.ProcessChanges 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Web/Modules/AccountModule.ascx.cs 文件。Duwamish7.Web.Secure.Logon.SubmitButton_Click 方法的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Web/Modules/AccountModule.ascx.cs 文件。
注意   如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.Web.Account.SubmitButton_Click 方法:
[C#]
/// <summary>
///     Validates then saves off the customer account information.
///     <param name="sender">The source of the event.</param>
///     <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
public void SubmitButton_Click(Object sender, EventArgs e)
{
    //
    // Process the changes to the form
    //
    ModuleAccount.ProcessChanges();
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub SubmitButton_Click:
'   Validates then saves off the customer account information.
' Parameters:
'   [in] Sender: Standard onlcick parameter for the sending object
'   [in] e: Standard click parameter for the event arguments
'----------------------------------------------------------------
Private Sub SubmitButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '
    ' Process the changes to the form
    '
    ModuleAccount.ProcessChanges
End Sub
Duwamish7.Web.AccountModule.ProcessChanges 方法:
[C#]
/// <summary>
///     Validates then saves off the customer account information.
///     <remarks>If this is a new customer, then create the item, or edit for an existing customer.</remarks>
///     <remarks>This is called from the page where this user control exists.</remarks>
///     <retvalue>Returns true on success, false otherwise.</retvalue>
/// </summary>
public bool ProcessChanges()
{
    //
    // Update the Database
    //
    if ( SaveCustomer() )
    {
        EditLabel.Visible = false;
        CreateLabel.Visible = false;
        UpdatedLabel.Visible = true;
       
        return true;
    }
    else
    {
        //
        // Show any errors
        //
        DisplayErrors();
       
        UpdatedLabel.Visible = false;
       
        return false;
    }
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub ProcessChanges:
'   Validates then saves off the customer account information.
'----------------------------------------------------------------
Public Function ProcessChanges() As Boolean
    Dim result As Boolean

    '
    ' Update the Database
    '
    result = SaveCustomer()
     If result Then
        EditLabel.Visible = False
        CreateLabel.Visible = False
        UpdatedLabel.Visible = True
    Else
        '
        ' Show any errors
        '
        DisplayErrors()
       
        UpdatedLabel.Visible = False
    End If

    ProcessChanges = result           
End Function
Duwamish7.Web.Secure.Logon.SubmitButton_Click 方法:
[C#]
/// <summary>
///     Validates  saves off the customer account information.
///     <param name="sender">The source of the event.</param>
///     <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
public void SubmitButton_Click(Object sender, EventArgs e)
{
    //
    // Create the account and trigger logon if it's good
    //
    if (ModuleAccount.ProcessChanges ())
    {
        //
        // Did we create on a redirect from account.
        //
        if (FormsAuthentication.GetRedirectUrl("*",false).EndsWith("account.aspx") )
        {
            //
            // Tell authentication that we're good.
            //
            FormsAuthentication.SetAuthCookie("*",false);
            //
            // Display proper panels
            //               
            ShowPanel(CreatedPanel, true);
            ShowPanel(LogonPanel, false);
            ShowPanel(DetailsPanel, false);
            ShowPanel(LoggedOnPanel, false);
        }
        else
        {   
            //
            // Tell authentication that we're good to go and redirect.
            //
            FormsAuthentication.RedirectFromLoginPage("*",false);
        }
    }
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub SubmitButton_Click:
'   Validates then saves off the customer account information.
' Parameters:
'   [in] sender: Standard onlcick parameter for the sending object
'   [in] e: Standard click parameter for the event arguments
'----------------------------------------------------------------
Private Sub SubmitButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '
    ' Create the account and trigger logon if it's good
    '
    If (ModuleAccount.ProcessChanges ()) Then
        '
        ' Did we create on a redirect from account.
        '
        If (FormsAuthentication.GetRedirectUrl("*",False).EndsWith("account.aspx") ) Then
            '
            ' Tell authentication that we're good.
            '
            FormsAuthentication.SetAuthCookie("*",False)
            '
            ' Display proper panels
            '               
            ShowPanel(CreatedPanel, True)
            ShowPanel(LogonPanel, False)
            ShowPanel(DetailsPanel, False)
            ShowPanel(LoggedOnPanel, False)
        Else
            '
            ' Tell authentication that we're good to go and redirect.
            '
            FormsAuthentication.RedirectFromLoginPage("*",False)
        End If
    End If
End Sub
业务外观源代码
Duwamish7.BusinessFacade.CustomerSystem.UpdateCustomer 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Business/Facade/CustomerSystem.cs 文件。Duwamish7.BusinessFacade.CustomerSystem.CreateCustomer 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Business/Facade/CustomerSystem.cs 文件。
注意   如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
BusinessFacade.CustomerSystem.UpdateCustomer 方法:
[C#]
/// <summary>
///     Updates a new customer.
///     <param name="customer">Customer's data.</param>
///     <retvalue>true if Update is successful: otherwise, false.</retvalue>
///     <exception> class='System.ApplicationException'>
///         The customer is null.
///     </exception>
/// </summary>
public bool UpdateCustomer(CustomerData customer)
{
    //
    // Check preconditions
    //
    ApplicationAssert.CheckCondition(customer != null, "Customer is required", ApplicationAssert.LineNumber);

   // recreate the salted password
   byte [] password = (byte[])customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0][CustomerData.PASSWORD_FIELD];
   customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0][CustomerData.PASSWORD_FIELD] = CreateDbPassword(password);
   return (new Customer()).Update(customer);
 }
[Visual Basic .NET]
'----------------------------------------------------------------
' Function UpdateCustomer:
'   Update the current customer with edited information.
' Returns:
'   True if update is successful
' Parameters:
'   [in]  customer: Customer's data
' Throws:
'   PreConditionException
' PreConditions:
'   customer is Not Nothing
'----------------------------------------------------------------
Public Function UpdateCustomer(ByVal customer as CustomerData) As Boolean
    '
    ' Check preconditions
    '
    ApplicationAssert.CheckCondition( Not customer Is Nothing, "Customer is required", ApplicationAssert.LineNumber)

    'recreate the salted password
    Dim password As Byte() = CType(customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0)(CustomerData.PASSWORD_FIELD), Byte())
    customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0)(CustomerData.PASSWORD_FIELD) = CreateDbPassword(password)
    With New Customer
        UpdateCustomer = .Update(customer)
    End With
End Function
Duwamish7.BusinessFacade.CustomerSystem.CreateCustomer:
[C#]
/// <summary>
///     Creates a new customer.
///     <remarks>custData is passed back as an out parameter for remoting.</remarks>
///     <param name="emailAddress">Customer's email address.</param>
///     <param name="password">Customer's account password.</param>
///     <param name="name">Customer's name.</param>
///     <param name="address">Customer's address.</param>
///     <param name="country">Customer's country.</param>
///     <param name="phoneNumber">Customer's phone number.</param>
///     <param name="fax">Customer's fax number.</param>
///     <param name="custData">Returns customer's data.</param>
///     <retvalue>true if Create is successful: otherwise, false.</retvalue>
/// </summary>
public bool CreateCustomer(String emailAddress,
                           byte [] password,
                           String name,
                           String address,
                           String country,
                           String phoneNumber,
                           String fax,
                           out CustomerData custData)
{
   // create a salted password
   byte [] saltedPassword = CreateDbPassword(password);

    //
    // Create a new row
    //
    custData = new CustomerData();
   
   DataTable table = custData.Tables[CustomerData.CUSTOMERS_TABLE];
    DataRow row = table.NewRow();
    //
    // Fill input data into new row
    //
    row[CustomerData.EMAIL_FIELD] = emailAddress;
    row[CustomerData.PASSWORD_FIELD] = saltedPassword;
    row[CustomerData.NAME_FIELD] = name;
    row[CustomerData.ADDRESS_FIELD] = address;
    row[CustomerData.COUNTRY_FIELD] = country;
    row[CustomerData.PHONE_FIELD] = phoneNumber;
    row[CustomerData.FAX_FIELD] = fax;
    //
    // Add it to the table
    //
    table.Rows.Add(row);
    //
    // Insert the customer using the business rules
    //
   return (new Customer()).Insert(custData);
}

      // create salted password to save in Db
      private byte [] CreateDbPassword(byte[] unsaltedPassword)
      {
         //Create a salt value
         byte[] saltValue = new byte[saltLength];
         RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
         rng.GetBytes(saltValue);
        
         return CreateSaltedPassword(saltValue, unsaltedPassword);
      }
     
      // create a salted password given the salt value
      private byte[] CreateSaltedPassword(byte[] saltValue, byte[] unsaltedPassword)
      {
         // add the salt to the hash
         byte[] rawSalted  = new byte[unsaltedPassword.Length + saltValue.Length];
         unsaltedPassword.CopyTo(rawSalted,0);
         saltValue.CopyTo(rawSalted,unsaltedPassword.Length);
        
         //Create the salted hash        
         SHA1 sha1 = SHA1.Create();
         byte[] saltedPassword = sha1.ComputeHash(rawSalted);

         // add the salt value to the salted hash
         byte[] dbPassword  = new byte[saltedPassword.Length + saltValue.Length];
         saltedPassword.CopyTo(dbPassword,0);
         saltValue.CopyTo(dbPassword,saltedPassword.Length);

         return dbPassword;
      }

      // compare the hashed password against the stored password
      private bool ComparePasswords(byte[] storedPassword, byte[] hashedPassword)
      {
         if (storedPassword == null || hashedPassword == null || hashedPassword.Length != storedPassword.Length - saltLength)
            return false;

         // get the saved saltValue
         byte[] saltValue = new byte[saltLength];
         int saltOffset = storedPassword.Length - saltLength;
         for (int i = 0; i < saltLength; i++)
            saltValue[i] = storedPassword[saltOffset + i];

         byte[] saltedPassword = CreateSaltedPassword(saltValue, hashedPassword);
     
         // compare the values
         return CompareByteArray(storedPassword, saltedPassword);
      }

      // compare the contents of two byte arrays
      private bool CompareByteArray(byte[] array1, byte[] array2)
      {
         if (array1.Length != array2.Length)
            return false;
         for (int i = 0; i < array1.Length; i++)
         {
            if (array1[i] != array2[i])
               return false;
         }
         return true;
      }
[Visual Basic .NET]
'----------------------------------------------------------------
' Function CreateCustomer:
'   Creates a new customer
' Returns:
'   True if Create is successful
' Parameters:
'   [in]  emailAddress: Customer's email address
'   [in]  password: Customer's account password
'   [in]  name: Customer's name
'   [in]  address: Customer's address
'   [in]  country: Customer's country
'   [in]  phoneNumber: Customer's phone number
'   [in]  fax: Customer's fax number
'   [out] custData : Returns customer's data
'----------------------------------------------------------------
Public Function CreateCustomer(ByVal emailAddress As String, _
                               ByVal password As Byte(), _
                               ByVal name As String, _
                               ByVal address As String, _
                               ByVal country As String, _
                               ByVal phoneNumber As String, _
                               ByVal fax As String, _
                               ByRef custData As CustomerData) As Boolean
    Dim row As DataRow  'used to access the Table
    Dim customerRules As Customer  'used for access to customer business rule

    'create a salted password
    Dim saltedPassword As Byte() = CreateDbPassword(password)

    '
    ' Create a new row
    '
    custData = New CustomerData()
    row = custData.Tables(CustomerData.CUSTOMERS_TABLE).NewRow

    '
    ' Fill input data into new row
    '
    With row
        .Item(CustomerData.EMAIL_FIELD) = emailAddress
        .Item(CustomerData.PASSWORD_FIELD) = saltedPassword
        .Item(CustomerData.NAME_FIELD) = name
        .Item(CustomerData.ADDRESS_FIELD) = address
        .Item(CustomerData.COUNTRY_FIELD) = country
        .Item(CustomerData.PHONE_FIELD) = phoneNumber
        .Item(CustomerData.FAX_FIELD) = fax
    End With

    '
    ' Add it to the table
    '
    custData.Tables(CustomerData.CUSTOMERS_TABLE).Rows.Add(row)

    '
    ' Insert the customer using the business rules
    '  
    With New Customer()
        CreateCustomer = .Insert(custData)
    End With
End Function

' create salted password to save in Db
Private Function CreateDbPassword(ByVal unsaltedPassword As Byte()) As Byte()
    'Create a salt value
    Dim saltValue(saltLength - 1) As Byte

    Dim rng As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()
    rng.GetBytes(saltValue)

    Return CreateSaltedPassword(saltValue, unsaltedPassword)
End Function

' create a salted password given the salt value
Private Function CreateSaltedPassword(ByVal saltValue As Byte(), ByVal unsaltedPassword As Byte()) As Byte()
    ' add the salt to the hash
    Dim rawSalted(unsaltedPassword.Length + saltValue.Length - 1) As Byte
    unsaltedPassword.CopyTo(rawSalted, 0)
    saltValue.CopyTo(rawSalted, unsaltedPassword.Length)

    'Create the salted hash        
    Dim sha1 As sha1 = sha1.Create()
    Dim saltedPassword As Byte() = sha1.ComputeHash(rawSalted)

    ' add the salt value to the salted hash
    Dim dbPassword(saltedPassword.Length + saltValue.Length - 1) As Byte
    saltedPassword.CopyTo(dbPassword, 0)
    saltValue.CopyTo(dbPassword, saltedPassword.Length)

    Return dbPassword
End Function

' compare the hashed password against the stored password
Private Function ComparePasswords(ByVal storedPassword As Byte(), ByVal hashedPassword As Byte()) As Boolean
    If ((storedPassword Is Nothing) Or (hashedPassword Is Nothing) Or (hashedPassword.Length <> storedPassword.Length - saltLength)) Then
        Return False
    End If

    ' get the saved saltValue
    Dim saltValue(saltLength - 1) As Byte
    Dim saltOffset As Integer = storedPassword.Length - saltLength
    Dim i As Integer = 0
    For i = 0 To saltLength - 1
        saltValue(i) = storedPassword(saltOffset + i)
    Next

    Dim saltedPassword As Byte() = CreateSaltedPassword(saltValue, hashedPassword)

    ' compare the values
    Return CompareByteArray(storedPassword, saltedPassword)
End Function

' compare the contents of two byte arrays
Private Function CompareByteArray(ByVal array1 As Byte(), ByVal array2 As Byte()) As Boolean
    If (array1.Length <> array2.Length) Then
        Return False
    End If

    Dim i As Integer
    For i = 0 To array1.Length - 1
        If (array1(i) <> array2(i)) Then
            Return False
        End If
    Next

    Return True
End Function
业务规则源代码
Duwamish7.BusinessRules.Customer.Update 方法和 Duwamish7.BusinessRules.Customer.Insert 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Business/Rules/Customer.cs 文件。
注意   如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.BusinessRules.Customer.Update 方法:
[C#]
/// <summary>
///     Validates and updates a new customer
///     <remarks>  
///         Returns customer data.  If there are fields that contain errors
///         that contain errors they are individually marked. 
///     </remarks>  
///     <param name="customer">CustomerData to be updated.</param>
///     <retvalue>true if successful; otherwise, false.</retvalue>
///     <exception> class='System.ApplicationException'>
///         An invalid customer was passed in.
///     </exception>
/// </summary>
public bool Update(CustomerData customer)
{
    //
    // Check Preconditions
    //
    ApplicationAssert.CheckCondition(customer != null,"customer Parameter cannot be null",ApplicationAssert.LineNumber);
    ApplicationAssert.CheckCondition(customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows.Count == 1,"customer Parameter can only contain 1 row",ApplicationAssert.LineNumber);
    //
    // Get the row and clear any existing errors
    //
    DataRow row = customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0];
    //
    // Do core validation
    //
    bool result = Validate(row);
    //
    // Do additional validation
    //
    if ( row.GetColumnError(CustomerData.EMAIL_FIELD) == String.Empty )
    {
        //
        // Email address passed format verification, now ensure that it
        // does not already exist in the database.
        //
        CustomerData existingCustomer = GetCustomerByEmail(row[CustomerData.EMAIL_FIELD].ToString());
       
        if ( null != existingCustomer )
        {
            //
            // Email is not unique - make sure the email address belongs this customer
            //
            if ( row[CustomerData.PKID_FIELD].ToString() != existingCustomer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0][CustomerData.PKID_FIELD].ToString() )
            {
                //
                // Customer PKID does not match, so this would create a duplicate email address
                //
                row.SetColumnError(CustomerData.EMAIL_FIELD, CustomerData.EMAIL_FIELD_NOT_UNIQUE); //email field is not unique
                row.RowError = CustomerData.INVALID_FIELDS;
               
                result = false;
            }
        }
    }
    //           
    // Update the customer if validation has passed
    //
    if ( result )
    {
        using (Customers customersAccess = new Customers())
            {
                result = customersAccess.UpdateCustomer(customer);
            }
    }
   
    return result;
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function Update:
'   Validates and updates a customer
' Returns:
'   true if update is successful
'   false if invalid fields exist
' Parameters:
'   [in]  customer: CustomerData to be updated
'   [out] customer : Returns customer data.  If there are fields
'                    that contain errors they are individually marked. 
'----------------------------------------------------------------
Public Function Update (ByVal customer as CustomerData) As Boolean
    '
    ' Check Preconditions
    '
    ApplicationAssert.CheckCondition(Not customer Is Nothing,"customer Parameter cannot be null",ApplicationAssert.LineNumber)
    ApplicationAssert.CheckCondition(customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows.Count = 1,"customer Parameter can only contain 1 row",ApplicationAssert.LineNumber)   
   
    Dim existingCustomer As CustomerData  'used to see if the customer already exists
    Dim result as Boolean
   
    '
    ' Do core validation
    '
     With customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0)
        result = Validate(customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0))
        '
        ' Do additional validation
        '
        If Len(.GetColumnError (CustomerData.EMAIL_FIELD)) < 1 Then
            '
            ' Email address passed format verification, now ensure that it
            ' does not already exist in the database.
            '
            existingCustomer = GetCustomerByEmail(CStr(.Item(CustomerData.EMAIL_FIELD)))
           
            If Not existingCustomer Is Nothing Then
                '
                ' Email is not unique - make sure the email address belongs this customer
                '
                If .Item(CustomerData.PKID_FIELD).ToString() <> existingCustomer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0).Item(CustomerData.PKID_FIELD).ToString() Then
                    '
                    ' customer PKID does not match, so this would create a duplicate email address
                    '
                    .SetColumnError(CustomerData.EMAIL_FIELD, CustomerData.EMAIL_FIELD_NOT_UNIQUE) 'email field is not unique
                    .RowError = CustomerData.INVALID_FIELDS
                   
                    result = false
                End If
            End If
        End If
    End With
    '           
    ' Update the customer if validation has passed
    '
    If result Then
        result = (New Customers()).UpdateCustomer(customer)
    End If   
   
    Update = result

    
End Function
Duwamish7.BusinessRules.Customer.Insert 方法:
[C#]
/// <summary>
///     Validates and inserts a new customer
///     <remarks>  
///         Returns customer data.  If there are fields that contain errors
///         that contain errors they are individually marked. 
///     </remarks>  
///     <param name="customer">CustomerData to be inserted.</param>
///     <retvalue>true if successful; otherwise, false.</retvalue>
///     <exception> class='System.ApplicationException'>
///         An invalid customer was passed in.
///     </exception>
/// </summary>
public bool Insert(CustomerData customer)
{
    //
    // Check Preconditions
    //
    ApplicationAssert.CheckCondition(customer != null,"customer Parameter cannot be null",ApplicationAssert.LineNumber);
    ApplicationAssert.CheckCondition(customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows.Count == 1,"customer Parameter can only contain 1 row",ApplicationAssert.LineNumber);
    //
    // Get the row
    //
    DataRow row = customer.Tables[CustomerData.CUSTOMERS_TABLE].Rows[0];
    //
    // Do core validation
    //
    bool result = Validate(row);
    //
    // Do additional validation
    //
    if ( row.GetColumnError(CustomerData.EMAIL_FIELD) == String.Empty )
    {
        //
        // Email address passed format verification, now ensure that it
        // does not already exist in the database.
        //
        CustomerData existingCustomer = GetCustomerByEmail(row[CustomerData.EMAIL_FIELD].ToString());
       
        if ( null == existingCustomer )
        {
            //
            // Email is unique, do the insert if there are no other errors
            //
            if ( result )
            {
                using (Customers customersDataAccess = new Customers())
                {
                    result = customersDataAccess.InsertCustomer(customer);
                }
            }
        }
        else
        {
            //
            // Email is not unique, flag the error
            //
            row.SetColumnError(CustomerData.EMAIL_FIELD, CustomerData.EMAIL_FIELD_NOT_UNIQUE);
           
            row.RowError = CustomerData.INVALID_FIELDS;
           
            result = false;
        }       
    }
    //
    // Return the result of the operation
    //           
    return result;
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function Insert:
'   Validates and Inserts a new customer
' Returns:
'   OK if Create is successful
'   InvalidFields if invalid fields exist
' Parameters:
'   [in]  customer: CustomerData to be inserted
'   [out] customer : Returns customer data.  If there are fields
'                    that contain errors they are individually marked. 
'----------------------------------------------------------------
Public Function Insert (ByVal customer as CustomerData) As Boolean
    '
    ' Check Preconditions
    '
    ApplicationAssert.CheckCondition(Not customer Is Nothing,"customer Parameter cannot be null",ApplicationAssert.LineNumber)
    ApplicationAssert.CheckCondition(customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows.Count = 1,"customer Parameter can only contain 1 row",ApplicationAssert.LineNumber)
   
    Dim tmpCustomer As CustomerData  'used to see if the customer already exists
    Dim result as Boolean
   
    With customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0)
        '
        ' Do core validation
        '
        result = Validate (customer.Tables(CustomerData.CUSTOMERS_TABLE).Rows(0))
        '
        ' Do additional validation
        '
        If Len(.GetColumnError (CustomerData.EMAIL_FIELD)) < 1 Then
            '
            ' Email address passed format verification, now ensure that it
            ' does not already exist in the database.
            '
            tmpCustomer = GetCustomerByEmail(CStr(.Item(CustomerData.EMAIL_FIELD)))
            If tmpCustomer Is Nothing Then
                'email is unique, Save off the new customer
                If result  Then
                    With New Customers
                        result = .InsertCustomer(customer)
                    End With
                End If
            Else
                '
                ' Email is not unique, flag the error
                '
                .SetColumnError(CustomerData.EMAIL_FIELD, CustomerData.EMAIL_FIELD_NOT_UNIQUE) 'email field is not unique
                .RowError = CustomerData.INVALID_FIELDS
                result = false
            End If       
        End If
    End With
    '
    ' Return the result of the operation
    '
    Insert = result       
End Function
数据访问源代码
Duwamish7.DataAccess.Customers.UpdateCustomer 方法和 Duwamish7.DataAccess.Customers.InsertCustomer 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/DataAccess/Customers.cs 文件。
注意   如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.DataAccess.Customers.UpdateCustomer 方法:
[C#]
/// <summary>
///     Sends the customer updates to the database.
///     <param name="customer">A CustomerData containing detailed customer information.</param>
///     <retvalue>Success or failure of the database update.</retvalue>
/// </summary>
public bool UpdateCustomer(CustomerData customer)
{
    if ( dsCommand == null )
    {
        throw new System.ObjectDisposedException( GetType().FullName );
    }           
    //
    // Get the command and update the database
    //
    dsCommand.UpdateCommand = GetUpdateCommand();
   
    dsCommand.Update(customer, CustomerData.CUSTOMERS_TABLE);
    //
    // Check for table errors to see if the update failed.
    //
    if ( customer.HasErrors )
    {
        customer.Tables[CustomerData.CUSTOMERS_TABLE].GetErrors()[0].ClearErrors();
        return false;
    }
    else
    {
        customer.AcceptChanges();
        return true;
    }
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function UpdateCustomer:
'   Sends the customer updates to the database.
' Returns:
'   Success or failure of the database update.
' Parameters:
'   [in]  customer: a dataset containing detailed customer information.
'----------------------------------------------------------------
Public Function UpdateCustomer(ByVal customer as CustomerData) As Boolean
    '
    ' Get the command and update the database
    '
    dsCommand.UpdateCommand = GetUpdateCommand
   
    dsCommand.Update(customer, CustomerData.CUSTOMERS_TABLE)
    '
    ' Check for table errors to see if the update failed.
    '
    If customer.HasErrors Then
        customer.Tables(CustomerData.CUSTOMERS_TABLE).GetErrors(0).ClearErrors
    Else
        customer.AcceptChanges
        UpdateCustomer = True
    End If       
End Function
Duwamish7.DataAccess.Customers.InsertCustomer 方法:
[C#]
/// <summary>
///     Inserts a new customer into the database.
///     <param name="customer">A CustomerData containing detailed customer information.</param>
///     <retvalue>Success or failure of the database insert.</retvalue>
/// </summary>
public bool InsertCustomer(CustomerData customer)
{
    if ( dsCommand == null )
    {
        throw new System.ObjectDisposedException( GetType().FullName );
    }           
   
    dsCommand.InsertCommand = GetInsertCommand();
   
    dsCommand.Update(customer, CustomerData.CUSTOMERS_TABLE);
    //
    // Check for table errors to see if the update failed.
    //
    if ( customer.HasErrors )
    {
        customer.Tables[CustomerData.CUSTOMERS_TABLE].GetErrors()[0].ClearErrors();
        return false;
    }
    else
    {
        customer.AcceptChanges();
        return true;
    }
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function InsertCustomer:
'   Inserts a new customer into the database.
' Returns:
'   Success or failure of the database insert.
' Parameters:
'   [in]  customer: a dataset containing detailed customer information.
'----------------------------------------------------------------
Public Function InsertCustomer(ByVal customer as CustomerData) As Boolean

    dsCommand.InsertCommand = GetInsertCommand
   
    dsCommand.Update(customer, CustomerData.CUSTOMERS_TABLE)
    '
    ' Check for table errors to see if the update failed.
    '
    If customer.HasErrors Then
        customer.Tables(CustomerData.CUSTOMERS_TABLE).GetErrors(0).ClearErrors
    Else
        customer.AcceptChanges
        InsertCustomer = True
    End If       
End Function
SPROC
SQL 存储过程的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Database/Sql/d7_sprocs.sql 文件。
注意   如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS。
UpdateCustomerAddress SPROC:
------------------------------------------------
-- UpdateCustomerAddress
------------------------------------------------
CREATE PROCEDURE UpdateCustomerAddress
    @CustomerId     Int,
    @Address        NVARCHAR(255) = NULL,
    @Country        NVARCHAR(40) = NULL,
    @PhoneNumber    NVARCHAR(30) = NULL,
    @Fax            NVARCHAR(30) = NULL
AS
    SET NOCOUNT ON

    -- Update an existing address record

    UPDATE Addresses
       SET Address = @Address,
           Country = @Country,
           PhoneNumber = @PhoneNumber,
           Fax = @Fax
     WHERE CustomerId = @CustomerId
       AND CustomerId IS NOT NULL

    RETURN 0
InsertCustomer SPROC:
--------------------------------------------------
-- InsertCustomer
--------------------------------------------------
CREATE PROCEDURE InsertCustomer
    @PKId           INT = NULL OUTPUT,
    @Email          NVARCHAR(50) = NULL,
    @Password       BINARY(24) = NULL,
    @Name           NVARCHAR(40) = NULL,
    @Address        NVARCHAR(255) = NULL,
    @Country        NVARCHAR(40) = NULL,
    @PhoneNumber    NVARCHAR(30) = NULL,
    @Fax            NVARCHAR(30) = NULL
AS
    SET NOCOUNT ON

    DECLARE @AddressId INT
    DECLARE @CustomerId INT

    SET XACT_ABORT ON

    BEGIN TRANSACTION
        -- Insert Values into the customer table
        INSERT Customers (Email,
                          Password,
                          Name)

        SELECT @Email,
               @Password,
               @Name

        -- Get the new Customer Identifier, return as OUTPUT param
        SELECT @PKId = @@IDENTITY

        -- Insert New Address record
        -- Retrieve Address reference into @AddressId
        EXEC InsertAddress @Address,
                           @Country,
                           @PhoneNumber,
                           @Fax,
                           @PKId,
                           @AddressId OUTPUT
    COMMIT TRANSACTION

    RETURN 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值