加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

酒店点餐系统开发详解(四)

发布时间:2020-12-12 15:19:50 所属栏目:MsSql教程 来源:网络整理
导读:酒店点餐系统开发详解(四) ——数据库模块设计 ? 在本系统中每个模块与数据库的一系列查询、插入、删除等操作是通过类 CDatabaSEOperation 进行的,所有的数据库操作都封装在这个类中。数据库功能的封装增加了模块的独立性和复用性,便于进行二次开发和软

酒店点餐系统开发详解(四)

——数据库模块设计

?

在本系统中每个模块与数据库的一系列查询、插入、删除等操作是通过类CDatabaSEOperation进行的,所有的数据库操作都封装在这个类中。数据库功能的封装增加了模块的独立性和复用性,便于进行二次开发和软件的修改。

本系统采用ADO对象进行数据库操作,故应在stdafx.h中添加“#import?"c:/program?files/common?files/system/ado/msado15.dll"?no_namespace?rename("EOF","_EOF")”(不包括引号),每个模块刚启动并连接数据库的操作如下:

BOOL?CCookTerminalApp::InitInstance()

{

……

AfxEnableControlContainer();

::CoInitialize(NULL);//初始化com环境

//网络连接初始化

AfxSocketInit(NULL);

//数据库连接

ConnectSQLServer();

……

}

//连接数据库

void?CCookTerminalApp::ConnectSQLServer()

{

CString?IP,User,Passwd;

int?Port;

GetPrivateProfileString("SQLServer","IP","local",IP.GetBuffer(20),20,".//default.ini");

IP.ReleaseBuffer();

GetPrivateProfileString("SQLServer","User","sa",User.GetBuffer(20),".//default.ini");

User.ReleaseBuffer();

GetPrivateProfileString("SQLServer","Passwd","",Passwd.GetBuffer(20),".//default.ini");

Passwd.ReleaseBuffer();

Port?=?GetPrivateProfileInt("SQLServer","Port",1433,".//default.ini");

//数据库连接初始化

m_DbOp.CreateInstance();

if(IP?==?"local")

m_DbOp.OpenLocalDatabase("DishesSystem");

else{

CString?str;

str.Format("%s,%d",IP,Port);

m_DbOp.OpenRemoteDatabase(str,"DishesSystem",Passwd);

}

}

CDatabaSEOperation的具体接口及实现如下:

1、创建实例

void?CDatabaSEOperation::CreateInstance()

{

cnn.CreateInstance(__uuidof(Connection));

rst.CreateInstance(__uuidof(Recordset));

}

2、打开本地数据库

void?CDatabaSEOperation::OpenLocalDatabase(CString?basename)

{

CString?str;

str.Format(_T("Provider=SQLOLEDB.1;Data?Source=(local);Initial?Catalog=%s;Integrated?Security=SSPI"),basename);

cnn->ConnectionString?= (_bstr_t)str;

try{

cnn->Open(L"",L"",adCmdUnspecified);

}catch(_com_error?&e){

CatchError(e);

}

}

3、打开远程数据库

void?CDatabaSEOperation::OpenRemoteDatabase(CString?source,?CString?basename,?CString?user,?CString?pwd)

{

CString?str;

str.Format(_T("Provider=SQLOLEDB.1;Data?Source=%s;Network?Library=DBMSSOCN;Initial?Catalog=%s;User?ID=%s;Password=%s"),source,basename,user,pwd);

cnn->ConnectionString?= (_bstr_t)str;

try{

cnn->Open(L"",adCmdUnspecified);

}catch(_com_error?&e){

CatchError(e);

}

}

4、打开记录集

BOOL?CDatabaSEOperation::OpenRecordset(CString?sqlstatement)

{

CloseRecordset();

try{

rst->CursorLocation?=?adUseClient;

rst->Open((_variant_t)sqlstatement,_variant_t((IDispatch?*)cnn,true),adOpenDynamic,adLockPessimistic,adCmdText);

}catch(_com_error?&e){

// CatchError(e);

return?FALSE;

}

return?TRUE;

}

5、关闭记录集

void?CDatabaSEOperation::CloseRecordset()

{

if(rst->State)

rst->Close();

}

6、返回记录集

_RecordsetPtr?CDatabaSEOperation::GetRecordset(CString?sqlstatement)

{

_RecordsetPtr?rst;

rst.CreateInstance(__uuidof(Recordset));

try{

rst->CursorLocation?=?adUseClient;

rst->Open((_variant_t)sqlstatement,adCmdText);

}catch(_com_error?&e){

// CatchError(e);

return?NULL;

}

return?rst;

}

7、插入新数据

BOOL?CDatabaSEOperation::InsertItem(CString?sqlstatement)

{

try{

cnn->Execute((_bstr_t)sqlstatement,NULL,adCmdText);

}catch(_com_error?&e){

CatchError(e);

return?FALSE;

}

return?TRUE;

}

8、修改数据

BOOL?CDatabaSEOperation::UpdateItem(CString?sqlstatement)

{

try{

cnn->Execute((_bstr_t)sqlstatement,adCmdText);

}catch(_com_error?&e){

CatchError(e);

return?FALSE;

}

return?TRUE;

}

9、删除数据

BOOL?CDatabaSEOperation::DeleteItem(CString?sqlstatement)

{

try{

cnn->Execute((_bstr_t)sqlstatement,adCmdText);

}catch(_com_error?&e){

CatchError(e);

return?FALSE;

}

return?TRUE;

}

10、返回属性值

CString?CDatabaSEOperation::GetAttrValues(CString?attr)

{

_variant_t?vt;

CString?values;

if(rst->_EOF?||?rst->BOF)

return?"";

try{

vt?=?rst->GetCollect((_variant_t)attr);

}catch(_com_error?&e){

CatchError(e);

return?"";

}

values?=?(LPCSTR)_bstr_t(vt);

return?values;

}

11、读取数据库图片数据

char?*CDatabaSEOperation::ReadPictureData(CString?sqlstatement,?CString?attrName)

{

_RecordsetPtr?temp_rst;

char?*buf?=?NULL;

temp_rst.CreateInstance(__uuidof(Recordset));

try{

temp_rst->Open((_variant_t)sqlstatement,adCmdText);

}catch(_com_error?&e){

CatchError(e);

return?NULL;

}

long?lDataSize;

try{

lDataSize?=?temp_rst->GetFields()->GetItem((_variant_t)attrName)->ActualSize;

}catch(_com_error?&e){

CatchError(e);

return?NULL;

}

if(lDataSize?>?0)

{

_variant_t varBLOB;

try{

varBLOB?=?temp_rst->GetFields()->GetItem((_variant_t)attrName)->GetChunk(lDataSize);

}catch(_com_error?&e){

CatchError(e);

return?NULL;

}

if(varBLOB.vt?==?(VT_ARRAY?|?VT_UI1))

{

if(buf?=?new?char[lDataSize+1]) ///重新分配必要的存储空间

{

char?*pBuf?=?NULL;

SafeArrayAccessData(varBLOB.parray,(void?**)&pBuf);

memcpy(buf,pBuf,lDataSize); ///复制数据到缓冲区

SafeArrayUnaccessData?(varBLOB.parray);

}

}

}

return?buf;

}

12、保存图片到数据库

BOOL?CDatabaSEOperation::SavePicture(CString?sqlstatement,?CString?attrName,?char?*buf,?long?len)

{

if(buf?==?NULL)

return?TRUE;

char *pBuf?=?buf;

VARIANT varBLOB;

SAFEARRAY *psa;

????SAFEARRAYBOUND rgsabound[1];

_RecordsetPtr?temp_rst;

temp_rst.CreateInstance(__uuidof(Recordset));

try{

temp_rst->Open((_variant_t)sqlstatement,adCmdText);

}catch(_com_error?&e){

CatchError(e);

return?FALSE;

}

if(temp_rst->_EOF)

return?FALSE;

if(pBuf)

{????

rgsabound[0].lLbound?=?0;

rgsabound[0].cElements?=?len;

psa?=?SafeArrayCreate(VT_UI1,?1,?rgsabound);

for?(long?i?=?0;?i?<?(long)len;?i++)

SafeArrayPutElement?(psa,?&i,?pBuf++);

varBLOB.vt?=?VT_ARRAY?|?VT_UI1;

varBLOB.parray?=?psa;

temp_rst->GetFields()->GetItem((_variant_t)attrName)->AppendChunk(varBLOB);

}

temp_rst->Update();

temp_rst->Close();

return?TRUE;

}

在实际的操作中,我们将常用的数据库操作整理为存储过程编译到数据库中,以下就是本系统所涉及的具体存储过程:

从厨师表中删除厨师(DeleteCook?@cookid?

1)本过程先查看点菜表中是否存在相关记录,若存在,则不允许删除厨师,因为顾客还没结账;若不存在,则先删除做菜表中记录,再删除厨师表中记录。

--删除厨师,需先将CookingTableDishedTable中的相关项删除

CREATE?PROCEDURE?DeleteCook?@cookid?char(8)

AS

--如果点菜表中含有相关项,说明顾客未结账,则不允许删除

IF?EXISTS?(SELECT?*?FROM?DishedTable?WHERE?cookid=@cookid)

?????RETURN

ELSE?

IF?EXISTS?(SELECT?*?FROM?CookingTable?WHERE?cookid=@cookid)

?????DELETE?FROM?CookingTable?WHERE?cookid=@cookid

DELETE?FROM?CookTable?WHERE?cookid=@cookid

2)从菜品表中删除菜品(DeleteDish?@dishid

本过程同样先检查点菜表中是否有相关项,若有,则不允许删除菜品;若无,则先删除做菜表中记录,再删除菜品表中记录。

--删除菜品信息,先检查DishedTableCookingTable中有无相关项

CREATE?PROCEDURE?DeleteDish?@dishid?char(8)

AS

--如果点菜表中含有相关项,说明顾客未结账,则不允许删除

IF?EXISTS?(SELECT?*?FROM?DishedTable?WHERE?dishid=@dishid)

??????RETURN

ELSE?

IF?EXISTS?(SELECT?*?FROM?CookingTable?WHERE?dishid=@dishid)

??????DELETE?FROM?CookingTable?WHERE?dishid=@dishid

DELETE?FROM?DishesTable?WHERE?dishid=@dishid

3)销售统计(SalesStatistics?@date,@sales

本过程首先检查表中是否存在日期相同的记录,若存在,则将原记录中的销售额加上新数据;若不存在,则直接插入新数据。

--销售统计函数

CREATE?PROCEDURE?SalesStatistics?@date?char(10),@sales?float

AS

--如果表中存在该项,则增加销售额

IF?EXISTS?(SELECT?*?FROM?SalesStatisticsTable?WHERE?date=@date)

????UPDATE?SalesStatisticsTable?SET?sales=sales+@sales?WHERE?date=@date

ELSE

--否则,插入新数据

????INSERT?INTO?SalesStatisticsTable?(date,sales)?VALUES(@date,@sales)

4)搜索拿手菜表(SearchSpecialty?@cookname

cookname'%%',则显示所有表中数据,否则,显示某一厨师的拿手菜信息。所返回结果先按厨师名排序,然后再按喜爱度排序。

--搜索拿手菜表

CREATE?PROCEDURE?SearchSpecialty?@cookname?nchar(50)

AS

IF?@cookname='%%'

???SELECT?DT.dishid?as?菜品编号,LEFT(dishname,LEN(dishname))?as?菜品名称,

???????????CT.cookid?as?厨师编号,LEFT(cookname,LEN(cookname))?as?厨师姓名,

???????????average?as?喜爱度,dishprice?as?菜品单价

???FROM?SpecialtyTable?ST?INNER?JOIN?DishesTable?DT?ON?ST.dishid=DT.dishid

?????????INNER?JOIN?CookTable?CT?ON?ST.cookid=CT.cookid

?????????ORDER?BY?cookname?ASC,average?DESC??--先按厨师名排序,再按平均分排序

ELSE

???SELECT?DT.dishid?as?菜品编号,dishprice?as?菜品单价

???FROM?SpecialtyTable?ST?INNER?JOIN?DishesTable?DT?ON?ST.dishid=DT.dishid

?????????INNER?JOIN?CookTable?CT?ON?ST.cookid=CT.cookid

???WHERE?cookname?LIKE?@cookname

?????????ORDER?BY?cookname?ASC,average?DESC???--先按厨师名排序,再按平均分排序

5)点菜(DishedFuction?@dishedtime?,@deskid?@dishid?,@cookid

本过程先查看表中是否存在相同记录,若存在,则将所点菜品份数amount1,菜品总价cost自动加上相应菜品单价;若不存在,则直接插入新数据。

--点菜操作

CREATE?PROCEDURE?DishedFuction?

???????@dishedtime?char(19),@deskid?int,@dishid?char(8),@cookid?char(8)

AS

DECLARE?@price?float

SELECT?@price=dishprice?FROM?DishesTable?WHERE?dishid=@dishid

IF?EXISTS?(SELECT?*?FROM?DishedTable?WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid)

?????UPDATE?DishedTable?SET?amount=amount+1,cost=cost+@price

????????WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid

ELSE

?????INSERT?INTO?DishedTable?(dishedtime,deskid,dishid,cookid,cost,amount)?

??????????????????VALUES(@dishedtime,@deskid,@dishid,@cookid,@price,1)

6)退菜(ReturnDishFuction?@dishedtime,@dishid

本过程先查看菜品份数amount是否为1,若为1,则直接删除该记录;若不为1,则将菜品份数amount1,然后菜品总价cost减去相应菜品单价。

--退菜操作

CREATE?PROCEDURE?ReturnDishFuction?

???????@dishedtime?char(19),@dishid?char(8)

AS????DECLARE?@price?float

SELECT?@price=dishprice?FROM?DishesTable?WHERE?dishid=@dishid

--如果点菜表中存在该项则将点菜份数-1,菜品总价递减

IF?EXISTS?(SELECT?*?FROM?DishedTable?WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid)

BEGIN??DECLARE?@amount?int

????????SELECT?@amount=amount?FROM?DishedTable?WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid

IF?@amount=1

???DELETE?FROM?DishedTable?WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid

ELSE???

????????UPDATE?DishedTable?SET?amount=amount-1,cost=cost-@price

????????WHERE?dishedtime=@dishedtime?AND?deskid=@deskid?AND?dishid=@dishid

END

7)评分(ScoreFuction?@cookid,@dishid?,@score

本过程先检查表中是否存在相同记录,若存在,则将评分次数freq1,总分scores加上此次分数,并计算平均分;若不存在,则插入新数据。

--对厨师所做菜品进行评分

CREATE?PROCEDURE?ScoreFuction?@cookid?char(8),@score?int

AS

--如果表中存在该项,则将评次加1,总分增加,并求出平均分

IF?EXISTS?(SELECT?*?FROM?CookingTable?WHERE?cookid=@cookid?AND?dishid=@dishid)

???BEGIN

??????DECLARE?@f?int,@s?int,@a?int

??????SELECT?@f=freq,@s=scores?FROM?CookingTable?WHERE?cookid=@cookid?AND?dishid=@dishid

??????SET?@f=@f+1

??????SET?@s=@s+@score

??????SET?@a=@s/@f

??????UPDATE?CookingTable?SET?freq=@f,scores=@s,average=@a

??????????????WHERE?cookid=@cookid?AND?dishid=@dishid

???END

ELSE

???INSERT?INTO?CookingTable?(cookid,freq,scores,average)?

????????????????VALUES(@cookid,1,@score,@score)

?

8)搜索点菜表(SearchDished?@dishedtime?,@deskid

本过程用于向顾客返回其所点菜品信息,并对厨师所做菜品进行评分。

--搜索点菜表

CREATE?PROCEDURE?SearchDished?@dishedtime?char(19),@deskid?int

AS

SELECT?DdT.dishid?as?菜品编号,

DdT.cookid?as?厨师编号,

amount?as?点菜份数,cost?as?菜品总价

FROM?DishedTable?DdT?INNER?JOIN?DishesTable?DsT?ON?DdT.dishid=DsT.dishid

??????????????INNER?JOIN?CookTable?CkT?ON?DdT.cookid=CkT.cookid

WHERE?dishedtime=@dishedtime?AND?deskid=@deskid

9)获取账单信息(GetAccountInfo?@dishedtime,@deskid

本过程用于结账时显示顾客所点菜品的详细信息。

--获取账单详细信息

CREATE?PROCEDURE?GetAccountInfo?@dishedtime?char(19),cost?as?总价

FROM?DishedTable?DdT?INNER?JOIN?DishesTable?DsT?ON?DdT.dishid=DsT.dishid

???????INNER?JOIN?CookTable?CkT?ON?DdT.cookid=CkT.cookid

WHERE?dishedtime=@dishedtime?AND?deskid=@deskid

10)搜索菜品表(SearchDishes?@dishname

本过程显示搜索菜品表的结果。

--搜索菜品表

CREATE?PROCEDURE?SearchDishes?@dishname?nchar(50)

AS

IF?@dishname='%%%%'

SELECT?dishid?as?菜品编号,dishprice?as?菜品单价

????FROM?DishesTable

ELSE

SELECT?dishid?as?菜品编号,dishprice?as?菜品单价

???FROM?DishesTable?WHERE?dishname?LIKE?@dishname

源代码下载地址:http://download.csdn.net/source/2406335?标题有误,请见谅...

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读