第6章 商品属性Word格式.docx
《第6章 商品属性Word格式.docx》由会员分享,可在线阅读,更多相关《第6章 商品属性Word格式.docx(16页珍藏版)》请在冰豆网上搜索。
第5章中通过数据库图表理解了数据表之间的关系。
这些数据表之间的联系的可视化表示如图Figure6-2。
Figure6-2.Diagramdescribingtherelationshipsamongthedatatablesrequiredtoimplement
productattributes
下面我们修改BalloonShop数据库,然后通过练习实现一个新的存储过程CatalogGetProductAttributeValues。
练一练:
为产品属性创建数据层的功能
1.打开SQLServerManagementStudio并执行如下代码,该代码将创建并构造Attribute数据表(你也可以通过VisualWebDeveloper来创建存储过程)。
--ConnecttotheBalloonShopdatabase
USEBalloonShop
--Createattributetable(storesattributessuchasSizeandColor)
CREATETABLEAttribute(
AttributeIDINTIDENTITY(1,1)NOTNULLPRIMARYKEY,
NameNVARCHAR(100)NOTNULL--e.g.Color,Size
)
--PopulateAttributetable
SETIDENTITY_INSERTAttributeON
INSERTINTOAttribute(AttributeID,Name)
VALUES(1,'
Color'
);
SETIDENTITY_INSERTAttributeOFF
注意:
我们使用SETIDENTITY_INSERTON(注意其中的下划线,原教材上没有),目的是在为数据表添加数据时,可以让我们自己来指定标识列的值。
除了此种情形之外,当一个字段是标识列(IDENTITY)字段时,数据库会为我们自动产生该标识列的ID值。
2.使用如下代码来创建并填充AttributeValuetable数据表:
--CreateAttributeValuetable(storesvaluessuchasYelloworXXL)
CREATETABLEAttributeValue(
AttributeValueIDINTIDENTITY(1,1)NOTNULLPRIMARYKEY,
AttributeIDINTNOTNULL,--TheIDoftheattribute
ValueNVARCHAR(100)NOTNULL--E.g.Yellow
--SettheIDENTITYINSERToptionforAttributeValue
SETIDENTITY_INSERTAttributeValueON;
--PopulateAttributeValuetable
INSERTINTOAttributeValue(AttributeValueID,AttributeID,Value)
SELECT1,1,'
White'
UNIONALL
SELECT2,1,'
Black'
SELECT3,1,'
Red'
SELECT4,1,'
Orange'
SELECT5,1,'
Yellow'
SELECT6,1,'
Green'
SELECT7,1,'
Blue'
SELECT8,1,'
Indigo'
SELECT9,1,'
Purple'
;
SETIDENTITY_INSERTAttributeValueOFF;
3.使用如下的代码创建并填充ProductAttributeValue数据表:
--CreateProductAttributeValuetable(associatesattributevaluesto
products)
CREATETABLEProductAttributeValue(
ProductIDINTNOTNULL,
AttributeValueIDINTNOTNULL,
PRIMARYKEY(ProductID,AttributeValueID)
--PopulateProductAttributeValuetable
INSERTINTOProductAttributeValue(ProductID,AttributeValueID)
SELECTp.ProductID,av.AttributeValueID
FROMproductp,AttributeValueav;
4.执行如下代码,该代码将创建外键并建立Figure6-2所示的数据表之间的联系。
--Createtheforeignkeys
ALTERTABLEAttributeValue
ADDCONSTRAINTFK_AttributeValue_Attribute
FOREIGNKEY(AttributeID)
REFERENCESAttribute(AttributeID)
GO
ALTERTABLEProductAttributeValue
ADDCONSTRAINTFK_ProductAttributeValue_AttributeValue
FOREIGNKEY(AttributeValueID)
REFERENCESAttributeValue(AttributeValueID)
ALTERTABLEProductAttributeValueWITHCHECK
ADDCONSTRAINTFK_ProductAttributeValue_Product
FOREIGNKEY(ProductID)
REFERENCESProduct(ProductID)
注意上面代码中的下划线,原教材中没有。
5.执行如下的SQL代码,将创建CatalogGetProductAttributeValues存储过程。
该存储过程将属性和一个产品相关联。
--CreateCatalogGetProductAttributeValuesstoredprocedure
CREATEPROCEDURECatalogGetProductAttributeValues
(@ProductIdINT)
AS
SELECTa.NameASAttributeName,
av.AttributeValueID,
av.ValueASAttributeValue
FROMAttributeValueav
INNERJOINattributeaONav.AttributeID=a.AttributeID
WHEREav.AttributeValueIDIN
(SELECTAttributeValueID
FROMProductAttributeValue
WHEREProductID=@ProductID)
ORDERBYa.Name;
解释该例是如何工作的:
产品属性的数据逻辑
我们将讨论创建并填充AttributeValue、ProductAttributeValue数据表以及CatalogGetProductAttributeValues存储过程的代码。
在讨论之前,确保你理解了Attribute,AttributeValue,和ProductAttributeValue数据表的每一个字段的含义以及填充这些数据表的代码。
我们先看看AttributeValue数据表。
为了填充该数据表,我们不是使用多个INSERT语句,而是使用INSERT...SELECT语句,该语句将允许我们插入由SELECT语句返回的结果。
然而,我们不是使用简单的SELECT语句来获取数据,我们使用了多个SELECT语句使用了UNIONALL。
总之,我们不是使用如下代码:
VALUES(1,1,'
VALUES(2,1,'
VALUES(3,1,'
...
而是使用如下代码:
UNIONALL...
如果你运行SQLServer2008,你可以使用更酷的方式来向数据表中插入多个值。
例如可以使用如下方式:
--PopulateAttributeValuetable--SQLSERVER2008syntax
INSERTINTOAttributeValue(AttributeValueID,AttributeID,value)
),(2,1,'
),(3,1,'
),...
当填充ProductAttributeValue数据表时,目的是想关联所有已存在属性值(通过AttributeValueID字段)到每一个产品(通过ProductID字段)。
在应用中,我们的产品是气球,我们想销售每一种可能颜色的产品。
填充ProductAttributeValue数据表的代码是使用INSERTINTO命令,该命令插入由SELECT查询得到的很多记录:
在我们的例子中,插入到ProductAttributeValue数据表的SELECT查询是一个交叉连接。
这种连接将产生两个集合的笛卡尔积(Cartesianproduct)。
结果是产生两个数据集的所有可能的组合。
例如,集合{1,2,3}和{a,b,c}的笛卡尔积,在数学上写为{1,2,3}×
{a,b,c},将会产生如下的数据集:
{{1,a},{1,b},{1,c},{2,a},{2,b},{2,c},{3,a},{3,b},{3,c}}。
在我们的例子中,如果创建已存在的产品IDs值和已存在的属性值的IDs值的笛卡尔积,我们将获得形式为(ProductID,AttributeValueID)元素的列表,这就是我们想增加到ProductAttributeValue数据表中的记录。
实现该交叉连接的SQL语法是:
例子数据中包含9个属性值和62个产品。
交叉连接操作将产生558(即9乘以62)条记录到ProductAttributeValue数据表中。
注意使用SELECT语句来创建交叉连接不是标准SQL,虽然这种形式为大多数数据库服务器认可。
正规的实现交叉查询的语法是使用CROSSJOIN语法:
FROMproductpCROSSJOINAttributeValueav;
如果不使用交叉连接(crossjoin),我们也可以使用前面介绍的UNION方法。
UNION将多个SELECT语句的结果累加成一个单独的结果集。
例如,如果将两个各有5条记录的查询进行联合(UNION),结果集将有10条记录。
当然,对于UNION来说,所有的查询必须返回类型相容、数量相同的字段,我们在这里不将详细讨论UNION。
例如,使用UNION,你可以仅仅增加特定的属性值到产品中,如下面的代码所示:
SELECTProductID,1ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,2ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,3ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,4ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,5ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,6ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,7ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,8ASAttributeValueIDFROMproduct
UNIONALLSELECTProductID,9ASAttributeValueIDFROMproduct;
最后,我们看看存储过程CatalogGetProductAttributeValues。
该存储过程接受一个参数ProductID,并返回产品属性的列表。
存储过程中的SQL代码返回带有AttributeName,AttributeValueID,andAttributeValue的产品列表:
你可以使用SQLServerManagementStudio来测试该存储过程,用值来替换参数的名字。
例如,你可以用一个产品的ID值来替换参数@ProductID,并执行该存储过程。
相应地,你也可以通过EXEC命令在SQLServerManagementStudio中执行存储过程(如下面的代码片段所示),或者右键点击存储过程在VisualWebDeveloper或者SQLServerManagementStudio中,并选择执行存储过程。
EXECCatalogGetProductAttributeValues1
该命令将返回具有产品ID值为1的结果。
如下图所示。
6.2 实现业务层(ImplementingtheBusinessTier)P207
实现业务层只需要编写调用CatalogGetProductAttributeValues存储过程的代码即可。
增加如下的代码到CatalogAccess类中,在App_Code/CatalogAccess.cs文件中。
//Retrievethelistofproductattributes
publicstaticDataTableGetProductAttributes(stringproductId)
{
//getaconfiguredDbCommandobject
DbCommandcomm=GenericDataAccess.CreateCommand();
//setthestoredprocedurename
comm.CommandText="
CatalogGetProductAttributeValues"
//createanewparameter
DbParameterparam=comm.CreateParameter();
param.ParameterName="
@ProductID"
param.Value=productId;
param.DbType=DbType.Int32;
comm.Parameters.Add(param);
//executethestoredprocedureandreturntheresults
returnGenericDataAccess.ExecuteSelectCommand(comm);
}
6.3 实现表示层(ImplementingthePresentationTier)
创建表示层的含义是增加相应的控件以允许用户从产品属性列表中选择相应的值。
属性值不是通过硬编码得到的,而是从数据库中读取的,这样在数据库中的属性值修改就可以直接反映到表示层中。
实现产品属性表示层
1.将ProductsList.ascx中Price处的代码修改为如下:
<
pclass="
DetailSection"
>
Price:
%#Eval("
Price"
"
{0:
c}"
)%>
/p>
asp:
PlaceHolderID="
attrPlaceHolder"
runat="
server"
/asp:
PlaceHolder>
2.增加如下的样式到BalloonShop.css文件中。
.DetailSection{
margin-top:
10px;
margin-bottom:
3.将ProductsList.ascx转换到DesignView,选择DataList控件,打开其属性窗口(使用F4快捷键)。
在属性窗口中选择事件图标,双击ItemDataBound事件实体。
4.增加如下的事件代码。
(注意需要导入System.Data名称空间,方法是在文件的开始位置使用usingSystem.Data;
语句)。
usingSystem.Data;
//Executedwheneachitemofthelistisboundtothedatasource
protectedvoidlistItemDataBound(objectsender,DataListItemEventArgse)
//obtaintheattributesoftheproduct
DataRowViewdataRow=(DataRowView)e.Item.DataItem;
stringproductId=d