“Search”(搜索)用户控件由 SearchModule 实现,它位于大多数 ASP.NET 页的左上角,并且使用下拉式列表框和相关联的文本框,使用户能够找到图书。下拉式列表中的选项是:
Title(标题)
ISBN
Author(作者)
Subject(主题)
实现
SearchModule 用户控件使用下面的 ASP.NET 文件和 C# 或 Visual Basic .NET 代码隐藏文件:
SearchModule.ascx
SearchModule.ascx.cs
SearchModule.ascx.vb
注意 有关 ASP.NET 代码隐藏的更多信息,请参见创建 ASP.NET Web 应用程序。
过程概述
用户从下拉式列表中选择搜索类型,如按“Author”(作者)。然后用户在文本框内输入想要的文本并单击“Go”(执行)按钮。“Go”按钮调用 Web 层的 Duwamish7.Web.SearchModule.SearchButton_Click 方法,该方法重定向到 ASP.NET“Search Results”(搜索结果)页,并将在下拉式列表和文本框中输入的搜索参数添加到 URL。下一步,Duwamish7.Web.SearchResults Page_Load 方法使用 URL 提供的搜索参数调用业务外观层的 Duwamish7.BusinessFacade.ProductSystem.GetSearchItems 方法。随后,Duwamish7.BusinessFacade.ProductSystem.GetSearchItems 方法调用相应的数据访问层的方法:
Duwamish7.DataAccess.Books.GetBooksByTitle 方法
调用 GetBooksByTitle 存储过程 (SPROC)。
Duwamish7.DataAccess.Books.GetBooksByISBN 方法
调用 GetBooksByISBN 存储过程 (SPROC)。
Duwamish7.DataAccess.Books.GetBooksByAuthor 方法
调用 GetBooksByAuthor 存储过程 (SPROC)。
Duwamish7.DataAccess.Books.GetBooksBySubject 方法
调用 GetBooksBySubject 存储过程 (SPROC)。
结构决策
作为用户控件实现搜索的决策最大化重用。因此,所有需要搜索功能的页都可以只是包括 SearchModule 用户控件。
若要查找适用于本主题中特定层的源代码,请单击相应的链接:
业务外观源代码 | 数据访问源代码 | SPROC
Web 源代码
Duwamish7.Web.SearchModule.SearchButton_Click 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Modules/SearchModule.ascx.cs 文件。Duwamish7.Web.SearchResults Page_Load 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Web/SearchResults.aspx.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.Web.SearchModule.SearchButton_Click 方法:
[C#]
/// <summary>
/// Collects user input and redirects information to the SearchResults page.
/// <param name="sender">The source of the event.</param>
/// <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
public void SearchButton_Click(Object sender, EventArgs e)
{
//
// Retrieve the search text
//
String searchText = SearchTextBox.Text.Trim();
//
// Redirect to search results page...
//
int index = SearchDropDownList.SelectedIndex;
Response.Redirect((new StringBuilder(PageBase.UrlBase))
.Append("/searchresults.aspx?type=")
.Append(index)
.Append("&fullType=")
.Append(Server.HtmlEncode(SearchDropDownList.Items[index].Text))
.Append("&text=")
.Append(Server.UrlEncode(searchText)).ToString(), false);
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub SearchButton_Click:
' SearchButton event handler. Collects user input and redirects
' information to the SearchResults page.
' Parameters:
' [in] sender: event sender
' [in] e: event arguments
'----------------------------------------------------------------
ublic Sub SearchButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SearchButton.Click
'
' Retrieve the search text
'
Dim searchText As String = Trim(SearchTextBox.Text)
'
' Redirect to search results page...
'
Dim index As Integer = SearchDropDownList.SelectedIndex
Dim url As StringBuilder = New StringBuilder(PageBase.UrlBase)
With url
.Append("/searchresults.aspx?type=")
.Append(index)
.Append("&fullType=")
.Append(Server.HtmlEncode(SearchDropDownList.Items(index).Text))
.Append("&text=")
.Append(Server.UrlEncode(searchText))
End With
Response.Redirect(url.ToString, False)
End Sub
Duwamish7.Web.SearchResults Page_Load 方法:
[C#]
/// <summary>
/// Performs search and loads datalist with results for display.
/// <remarks>Called whenever the page is loaded.</remarks>
/// <param name="sender">The source of the event.</param>
/// <param name="e">An EventArgs that contains the event data.</param>
/// </summary>
protected void Page_Load(Object sender, EventArgs e)
{
if (IsPostBack)
{
//
// Avoid a refresh problem if the user has left the search
// string empty by rerunning last search.
//
if ( ModuleSearch.SearchTextBox.Text.Trim() != String.Empty )
{
return;
}
}
Duwamish7.DataAccess.Books.SearchTypeEnum searchEnumType; //type of search used
DataSet resultsSet = null; //search results returned from facade
searchEnumType = (Duwamish7.DataAccess.Books.SearchTypeEnum)Int32.Parse(Request.QueryString["type"]);
searchType = Request.QueryString["fullType"].ToString();
searchText = Request.QueryString["text"].ToString();
if (searchText != String.Empty)
{
try
{
resultsSet = (new ProductSystem()).GetSearchItems(searchEnumType, searchText);
}
catch (ApplicationException)
{
// Fall into next if block for remaining settings
}
// Other exceptions throw
}
//handle error case where resultsSet is Nothing
if (null == resultsSet)
{
SearchTypeLabel.Text = Server.HtmlEncode(searchType);
ResultCountLabel.Text = Server.HtmlEncode("0");
SearchTextLabel.Text = Server.HtmlEncode(searchText);
return;
}
DataTable table = resultsSet.Tables[0];
resultsDataView = table.DefaultView;
SearchTypeLabel.Text = Server.HtmlEncode(searchType);
ResultCountLabel.Text = Server.HtmlEncode(table.Rows.Count.ToString());
SearchTextLabel.Text = Server.HtmlEncode(searchText);
//
// Remind the page that it needs bind its controls to there data.
//
DataBind();
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Sub SearchResults_Load:
' Called whenever the page is loaded. Performs search and
' loads datalist with results for display.
'----------------------------------------------------------------
Protected Sub SearchResults_Load(ByVal sender As System.Object, ByVal e As System.EventArgs)
If Me.IsPostBack Then
'
' Avoid a refresh problem if the user has left the search
' string empty by rerunning last search.
'
If ModuleSearch.SearchTextBox.Text.Trim() <> String.Empty Then
Exit Sub
End If
End If
Dim searchEnumType As Integer 'type of search used
Dim resultsSet As DataSet 'search results returned from facade
searchEnumType = CInt(request.querystring("type"))
searchType = request.querystring("fullType")
searchText = request.querystring("text")
If Len(searchText) > 0 Then
With New ProductSystem() 'create ProductSystem facade layer
Try
resultsSet = .GetSearchItems(searchEnumType, searchText)
Catch ae As ApplicationException
SearchTypeLabel.Text = Server.HtmlEncode(searchType)
ResultCountLabel.Text = Server.HtmlEncode("0")
SearchTextLabel.Text = Server.HtmlEncode(searchText)
Exit Sub
End Try
End With
End If
'handle error case where resultsSet is Nothing
If resultsSet Is Nothing Then
SearchTypeLabel.Text = Server.HtmlEncode(searchType)
ResultCountLabel.Text = Server.HtmlEncode("0")
SearchTextLabel.Text = Server.HtmlEncode(searchText)
Exit Sub
End If
resultsDataView = resultsSet.Tables(0).DefaultView
Dim row As DataRow
SearchTypeLabel.Text = Server.HtmlEncode(searchType)
ResultCountLabel.Text = Server.HtmlEncode(CStr(resultsSet.Tables(0).Rows.Count))
SearchTextLabel.Text = Server.HtmlEncode(searchText)
'
' Remind the page that it needs bind its controls to there data.
'
DataBind
End Sub
业务外观源代码
Duwamish7.BusinessFacade.ProductSystem.GetSearchItems 方法源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/Business/Facade/ProductSystem.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
Duwamish7.BusinessFacade.ProductSystem.GetSearchItems 方法:
[C#]
/// <summary>
/// Retrieves a dataset containing all the items that fullfill a search criteria.
/// <param name="searchType">Specifies the type of search to be performed.</param>
/// <param name="searchText">The text to search for.</param>
/// <retvalue>A BookData dataset containing all the items that fulfill the search criteria.</retvalue>
/// <exception> class='System.ApplicationException'>
/// The searchType is not within the correct range, or searchText is empty.
/// </exception>
/// </summary>
public BookData GetSearchItems(Books.SearchTypeEnum searchType, String searchText)
{
//
// Check preconditions
//
ApplicationAssert.CheckCondition(searchText != String.Empty, "searchText is required", ApplicationAssert.LineNumber);
//
// Make sure we have a valid request
//
searchText = (new StringBuilder(searchText)).Replace("/"", "/"/"").ToString();// Watch out for quote
//
// Use the correct search
//
using (Books bookDataAccess = new Books())
{
BookData retVal = null;
switch (searchType)
{
case Books.SearchTypeEnum.Author:
retVal = bookDataAccess.GetBooksByAuthor(searchText);
break;
case Books.SearchTypeEnum.ISBN:
retVal = bookDataAccess.GetBooksByISBN(searchText);
break;
case Books.SearchTypeEnum.Subject:
retVal = bookDataAccess.GetBooksBySubject(searchText);
break;
case Books.SearchTypeEnum.Title:
retVal = bookDataAccess.GetBooksByTitle(searchText);
break;
default:
ApplicationAssert.Check(false, "searchType " + searchType.ToString() + " is not valid", ApplicationAssert.LineNumber);
break;
}
return retVal;
}
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function GetSearchItems:
' Retrieves a dataset containing all the items that fullfill a
' search criteria
' Returns:
' A dataset containing all the items that Fulfill the search
' criteria.
' Parameters:
' [in] searchType: Specifies the type of search to be performed
' [in] searchText: The text to search for
' Throws:
' PreConditionException
' PreConditions:
' searchType is not within the correct range
' searchText is empty
'----------------------------------------------------------------
Public Function GetSearchItems(ByVal searchType As Integer, ByVal searchText As String) As BookData
'
' Check preconditions
'
ApplicationAssert.CheckCondition(Len(searchText) > 0, "searchText is required", ApplicationAssert.LineNumber)
Dim bookDataAccess As Books
'
' Make sure we have a valid request
'
searchText = Replace(searchText, """", """""") 'watch out for quotes
'
'Use the correct search
'
bookDataAccess = New Books
Select Case searchType
Case Books.SearchTypeEnum.Author
GetSearchItems = bookDataAccess.GetBooksByAuthor(searchText)
Case Books.SearchTypeEnum.ISBN
GetSearchItems = bookDataAccess.GetBooksByISBN(searchText)
Case Books.SearchTypeEnum.Subject
GetSearchItems = bookDataAccess.GetBooksBySubject(searchText)
Case Books.SearchTypeEnum.Title
GetSearchItems = bookDataAccess.GetBooksByTitle(searchText)
Case Else
ApplicationAssert.Check( False, "searchType " & searchType & " is not valid", ApplicationAssert.LineNumber)
End Select
'Clean up
bookDataAccess = Nothing
End Function
数据访问源代码
Duwamish7.DataAccess.Books.GetBooksByAuthor 方法和 FillBookData Helper 函数源代码的默认位置是 [安装 Visual Studio .NET 的驱动器号]:/Program Files/Microsoft Visual Studio .NET 2003/Enterprise Samples/Duwamish 7.0 CS/DataAccess/Books.cs 文件。
注意 如果安装了 Visual Basic .NET 版本,则 Duwamish 7.0 VB 将替换路径中的 Duwamish 7.0 CS,其文件名相同,但扩展名是 vb 而不是 cs。
注意 Duwamish7.DataAccess.Books.GetBooksByTitle、Duwamish7.DataAccess.Books.GetBooksByISBN 和 Duwamish7.DataAccess.Books.GetBooksBySubject 方法都遵循相似的模式。
Duwamish7.DataAccess.Books.GetBooksByAuthor 方法:
[C#]
/// <summary>
/// Retrieves all books for a specified authors name.
/// <param name="searchText">Search string containing an authors name in part or whole.</param>
/// <retvalue>BookData, a dataset containing detailed book information..</retvalue>
/// </summary>
public BookData GetBooksByAuthor(String searchText)
{
return FillBookData("GetBooksByAuthor", "@Author", searchText );
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function GetBooksByAuthor:
' Retrieves all books for a specified authors name.
' Returns:
' BookData, a dataset containing detailed book information.
' Parameters:
' [in] searchText: search string containing an authors name in part or whole.
'----------------------------------------------------------------
Public Function GetBooksByAuthor(ByVal searchText As String) As BookData
GetBooksByAuthor = FillBookData("GetBooksByAuthor", "@Author", searchText)
End Function
FillBookData Helper 函数:
[C#]
//----------------------------------------------------------------
// Function FillBookData:
// Helper function to create and populate a BookData dataset
// Returns:
// BookData, a dataset containing detailed book information.
// Parameters:
// [in] commandText: sql stored procedure to run.
// [in] paramName: sql paramater name.
// [in] paramValue: sql paramater.
//----------------------------------------------------------------
private BookData FillBookData(String commandText, String paramName, String paramValue)
{
if (dsCommand == null )
{
throw new System.ObjectDisposedException( GetType().FullName );
}
BookData data = new BookData();
SqlCommand command = dsCommand.SelectCommand;
command.CommandText = commandText;
command.CommandType = CommandType.StoredProcedure; // use stored proc for perf
SqlParameter param = new SqlParameter(paramName, SqlDbType.NVarChar, 255);
param.Value = paramValue;
command.Parameters.Add(param);
dsCommand.Fill(data);
return data;
}
[Visual Basic .NET]
'----------------------------------------------------------------
' Function FillBookData:
' Helper function to create and populate a BookData dataset
' Returns:
' BookData, a dataset containing detailed book information.
' Parameters:
' [in] cmdText: sql stored procedure to run.
' [in] paramName: sql paramater name.
' [in] paramValue: sql paramater.
'----------------------------------------------------------------
Private Function FillBookData(ByVal cmdText As String, ByVal paramName As String, ByVal paramValue As String) As BookData
Dim data As BookData
data = New BookData
With dsCommand
Try
With .SelectCommand
.CommandType = CommandType.StoredProcedure ' use stored proc for perf
.CommandText = cmdText
Dim param As SqlParameter = new SqlParameter(paramName, SqlDbType.NVarChar, 255)
param.Value = paramValue
.Parameters.Add(param)
End With
.Fill(data)
Finally
If Not .SelectCommand Is Nothing Then
If Not .SelectCommand.Connection Is Nothing Then
.SelectCommand.Connection.Dispose()
End If
.SelectCommand.Dispose()
End If
.Dispose()
End Try
End With
FillBookData = data
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。
提示 GetBooksByTitle、GetBooksByISBN 和 GetBooksBySubject 存储过程遵循相似的模式。
GetBooksByAuthor SPROC:
--------------------------------------------------
-- GetBooksByAuthor
--------------------------------------------------
CREATE PROCEDURE GetBooksByAuthor
@Author NVARCHAR(40)
AS
SET NOCOUNT ON
SELECT DISTINCT TOP 50
i.PKId,
i.TypeId,
b.PublisherId,
b.ISBN,
i.ImageFileSpec,
i.Name 'Title',
i.Description,
i.UnitPrice,
i.UnitCost,
t.Name 'ItemType',
p.Name 'PublisherName'
FROM Items i,
ItemType t,
Books b,
Publishers p,
BookAuthor k,
Authors a
WHERE CHARINDEX(@Author, a.Name) > 0
AND i.PKId = b.ItemId
AND k.ItemId = b.ItemId
AND a.PKId = k.AuthorId
AND i.TypeId = t.PKId
AND b.PublisherId = p.PKId
ORDER BY i.PKId
RETURN 0