“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