电子商务之数据存储流程(五)
首先我想还是给大家过一遍数据存储的流程吧。选个最简单的例子,用户登录,将用户从数据库中取出来。
首先需要在SQL数据库中编写存储过程,选存储过程+传递参数用SqlParameter是因为,除非是ADO.NET有漏洞,那么就绝对不会发生SQL注入。据我所知SQL注入发生在借用用户输入拼接生成SQL语句的地方。其次执行数据操作的性能也提高了。

CREATEPROCEDURE[dbo].[EndUserLogin_Select]
@Emailnvarchar(50),
@Passwordnvarchar(50)
AS
SELECTEndUserID,
EndUserTypeID,
UserName,
dt_EndUser.AddressID,
dt_EndUser.ContactInformationID,
Password,
IsSubscribed,
Phone,
Phone2,
Fax,
FROMdt_EndUser
INNERJOINdt_ContactInformation
ONdt_ContactInformation.ContactInformationID=dt_EndUser.ContactInformationID
WHEREEmail=@Email
ANDPassword=@Password
ANDEndUserTypeID=1
说明下,现在电子商务很流行采用邮箱或手机号来作为账号,而本网站就是采用的邮箱作为登录账号,所有有两个参数一个是@Email 和 @Password。这里因为邮箱在dt_ContactInformation表中所以查找的时候要将dt_EndUser和dt_ContactInformation合并起来通过ContactInformationID字段,EndUserTypeID=1代表用户类型是会员。
还记得我们电子商务之框架分析(一)时在Shop.DataAccess类库下的StoredProcedure类吗?接下来就在该类枚举型Name里面加入EndUserLogin_Select即存储过程名称。
然后我们就可以在Shop.DataAccess类库下实现与数据库的连接,在该类库下首先创建一个Select文件夹,所有对数据库进行Select操作的类都可以放在该文件夹下(当然你这里自己可以在细分)。在Select文件夹下创建一个EndUserLoginSelectData类

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingShop.Common;
usingSystem.Data.SqlClient;
usingSystem.Data;
namespaceShop.DataAccess.Select
{
///<summary>
///继承了基类DataAccessBase
///</summary>
publicclassEndUserLoginSelectData:DataAccessBase
{
//属性
publicEndUserEntityEndUser{set;get;}
///<summary>
///构造函数将存储过程的名称赋值给该类StoredprocedureName属性
///</summary>
publicEndUserLoginSelectData()
{
this.StoredprocedureName=StoredProcedure.Name.EndUserLogin_Select.ToString();
}
publicDataSetGet()
{
DataSetds;
//完成将添加SqlParameter
EndUserLoginSelectDataParametersenduserloginselectdataparameters=newEndUserLoginSelectDataParameters(this.EndUser);
DataBaseHelperdbhelper=newDataBaseHelper(this.StoredprocedureName);
//执行对数据库的操作
ds=dbhelper.Run(base.ConnectionString,enduserloginselectdataparameters.Parameters);
returnds;
}
}
///<summary>
///参数类
///</summary>
publicclassEndUserLoginSelectDataParameters
{
publicEndUserEntityEndUser{set;get;}
publicSqlParameter[]Parameters{set;get;}
publicEndUserLoginSelectDataParameters(EndUserEntityenduser)
{
this.EndUser=enduser;
Build();
}
privatevoidBuild()
{
SqlParameter[]parameters=
{
newSqlParameter("@Email",EndUser.UserContactInformation.Email),
newSqlParameter("@Passwrod",EndUser.Password)
};
this.Parameters=parameters;
}
}
}
这段代码有一定的难度,因为它封装了许多东西。基类DataAccessBase的代码在电子商务之框架分析(一)已经给出了。那么该类有3个属性分别为:
EndUser,
StoredprocedureName,
ConnectionString
这里构造函数只是初始化StoredprocedureName属性,将我们刚才建立的存储过程名称赋值给该属性。
这里也没有采用平常(个人的认为)写法,直接编写SqlParameter,而是较为复杂的编写了一个EndUserLoginSelectDataParameters类,该类完成了SqlPrameter的建立。最后调用个dbhelper.Run(base.ConnectionString,enduserloginselectdataparameters.Parameters)(this.ConnectionString也可以)就可以得到查询的数据。dbhelper.Run也在电子商务之框架分析(一)中有具体代码,Run是一个重载的函数,其实就是调用的SQLHlper类中的一些方法来完成对数据库的操作。

usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingShop.Common;
usingShop.DataAccess.Select;
usingSystem.Data;
namespaceShop.BusinessLogic
{
publicclassProcessEndUserLogin:IBusinessLogic
{
publicEndUserEntityEndUser{set;get;}
publicDataSetResultSet{set;get;}
publicboolIsAuthenticated{set;get;}
publicProcessEndUserLogin()
{
}
#regionIBusinessLogic成员
publicvoidInvoke()
{
EndUserLoginSelectDataenduserloginselectdata=newEndUserLoginSelectData();
enduserloginselectdata.EndUser=this.EndUser;
this.ResultSet=enduserloginselectdata.Get();
if(ResultSet.Tables[0].Rows.Count!=0)
{
this.IsAuthenticated=true;
EndUser.EndUserID=int.Parse(this.ResultSet.Tables[0].Rows[0]["EndUserID"].ToString());
EndUser.UserName=this.ResultSet.Tables[0].Rows[0]["UserName"].ToString();
EndUser.AddressID=int.Parse(this.ResultSet.Tables[0].Rows[0]["AddressID"].ToString());
EndUser.ContactInformationID=int.Parse(this.ResultSet.Tables[0].Rows[0]["ContactInformationID"].ToString());
EndUser.Password=ResultSet.Tables[0].Rows[0]["Password"].ToString();
ProcessGetAddressgetaddress=newProcessGetAddress();
getaddress.Address.AddressID=EndUser.AddressID;
getaddress.Invoke();
EndUser.UserAddress=getaddress.Address;
ProcessGetContactInformationgetcontactinformation=newProcessGetContactInformation();
getcontactinformation.ContactInformation.ContactInformationID=EndUser.ContactInformationID;
getcontactinformation.Invoke();
EndUser.UserContactInformation=getcontactinformation.ContactInformation;
}
}
#endregion
}
}
接下来就要在业务逻辑层(Shop.BusinessLogic)添加一个ProcessAddEndUser类
该类实现了IBusinessLogic接口(该接口也在电子商务之框架分析(一)给出了)这已经很清楚了就是先要给该类属性EndUser赋值(两个参数)然后调用上面的Get方法就得到了该用户的相关信息(this.ResultSet),查看该DataSet类型数据表存不存在数据,如果没有就说明账号或密码错误,有将这些信息赋值诶EndUser类型的数据。下面的就是得到用户一些信息又去数据库查询一些而外的信息,这里就不再详细讲解。
最后在页面层的Login页面的.cs文件加入一些代码

usingSystem;
usingSystem.Data;
usingSystem.Configuration;
usingSystem.Collections;
usingSystem.Web;
usingSystem.Web.Security;
usingSystem.Web.UI;
usingSystem.Web.UI.WebControls;
usingSystem.Web.UI.WebControls.WebParts;
usingSystem.Web.UI.HtmlControls;
usingShop.Common;
usingShop.BusinessLogic;
publicpartialclassLogin:BasePage
{
protectedvoidPage_Load(objectsender,EventArgse)
{
textUsername.Focus();
}
protectedvoidcommandLogin_Click(objectsender,EventArgse)
{
if(IsValid)
{
EndUserEntityenduser=newEndUserEntity();
ProcessEndUserLoginprocesslogin=newProcessEndUserLogin();
enduser.UserContactInformation.Email=textUsername.Text;
enduser.Password=textPassword.Text;
processlogin.EndUser=enduser;
try
{
processlogin.Invoke();
}
catch
{
Response.Redirect("ErrorPage.aspx");
}
if(processlogin.IsAuthenticated)
{
Response.Cookies["Authenticated"].Value="True";
base.CurrentEndUser=processlogin.EndUser;
if(Request.Cookies["ReturnURL"]!=null)
{
Response.Redirect(Request.Cookies["ReturnURL"].Value);
}
else
{
Response.Redirect("Account/CustomerOrders.aspx");
}
}
else
{
labelMessage.Text="Invalidlogin!";
}
}
}
}
这里我想要说明一点就是try...catch的用法,用得非常好,如果processlogin.Invoke();就是我们刚才写的那么多代码里发生的错误或异常在这里就可以轻松捕抓到并向用户提示页面出错,我个人以前在这方面会忽略,所以认为这里很经典
,注意到这里用户的密码没有加密,我们也可自己调用System.Web.Security.FormsAuthencation.HashPasswordForStoringInConfigFile()进行加密。下面的一些代码会涉及到很多内容我会在下面的内容和大家一起分析(注意到页面继承的BasePage类,而不是我们经常看到System.Web.UI.Page类)另外要强调的是,要注意引用这些程序集,例如我们在Shop.DataAccess添加引用项目Shop.Common类库,Shop.BusinessLogic添加引用Shop.DataAccess类库以及Shop.Common类库等等相信大家这个都会吧 -_-