在開發好友系統時, 做了個功能叫做推薦名單, 也就是將最近對戰的玩家記錄到數據表上, 再推給客戶端, 但在獲取數據時發現必須過濾掉已經添加的清單, 索性在表格上添加了一個字段來紀錄是否有效

後來發現Chloe處理這段很麻煩, 沒查到官方有 replace 的功能, 所以自己用了 procedure 來處理, 有點久沒用研究了下 Chole 怎麼調用
官方文檔說明
https://github.com/shuxinqin/Chloe/wiki/Oracle-procedure

兩個寫法不一樣, dbContext.SqlQuery 是直接獲取 Procedure 返回數據的, 就譬如 procedure 最後面寫了 select * from user limit 1; 可以透過這個方式獲取返回的 user 資料, 而 ExecuteNonQuery("Proc_GetPersonName", CommandType.StoredProcedure, id, outputName) 則是透過 Procedure 的 out 獲取數據
我們在更新 recent 表格同時也要獲取 recent 數據, 作法如果
DbParam iUserId = new DbParam("@iUserId", userId);
DbParam iRUserId = new DbParam("@iRUserId", recentUserId);
DbParam iState = new DbParam("@iState", 1);
dbContext.SqlQuery<Tbl_Recent>("proc_update_recent", CommandType.StoredProcedure, iUserId, iRUserId, iState);
這是一個沒有 return 的 procedure 調用方式, Procedure 如下
CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `proc_update_recent`(
IN `iUserId` int,
IN `iRUserId` int,
IN `iState` int)
BEGIN
DECLARE ts long;
set ts = (UNIX_TIMESTAMP() * 1000) + (MICROSECOND(NOW(3)) / 1000);
REPLACE into `recent`(`UserId` ,`RUserId`, `State`)
value
(iUserId, iRUserId, iState);
END
另外得益於使用 Procedure , 在發送邀請功能上需要判斷很多情況, 如果在 c# 處理邏輯就會很繁瑣, 後來使用 Procedure 解決, 如下
CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `proc_check_send_friendApply`(
IN `iApplyUserId` BIGINT,
IN `iApplyUserName` VARCHAR(64),
IN `iApplyUserHead` VARCHAR(128),
IN `iToUserId` BIGINT, OUT `oData` INT)
MAINLOOP:BEGIN
# declare timestamp
DECLARE ts BIGINT(20) default 0;
DECLARE isMyFriend TINYINT(4) default 0;
DECLARE findRecent TINYINT(4) default 0;
DECLARE findFriend TINYINT(4) default 0;
DECLARE findApply TINYINT(4) default 0;
set ts = (UNIX_TIMESTAMP() * 1000) + (MICROSECOND(NOW(3)) / 1000);
#已經是我的好友, 退出流程
select count(*) into isMyFriend from `friend` where `UserId`=iApplyUserId and `FUserId`=iToUserId;
if isMyFriend != 0 then
LEAVE MAINLOOP;
end if;
#if 如果Recent裡面有數據, 就改掉 state = 1
select count(*) into findRecent from `recent` where `UserId`=iApplyUserId and `RUserId`=iToUserId;
if findRecent != 0 then
REPLACE into `recent`(`UserId` ,`RUserId`,`State`) value (iApplyUserId, iToUserId, 1);
end IF;
#if 對方已經是好友就直接加回去,
select count(*) into findFriend from `friend` where `UserId`=iToUserId and `FUserId`=iApplyUserId;
if findFriend != 0 then
REPLACE into `friend`(`UserId` ,`FUserId`,`CreateTime`, `UpdateTime`) value (iApplyUserId, iToUserId, ts, ts);
set oData = 2;
LEAVE MAINLOOP;
end if;
#如果沒有邀請過就發邀請
select count(*) into findApply from `friendapply` where `ApplyUserId`=iApplyUserId and `ToUserId`=iToUserId;
if findApply = 0 then
REPLACE into `friendapply`(`ApplyUserId` ,`ApplyUserName`, `ApplyUserHead`, `ToUserId`, `State`, `CreateTime`, `UpdateTime`)
value
(iApplyUserId, iApplyUserName, iApplyUserHead, iToUserId, 0, ts, 0);
select * from `friendapply` where `ApplyUserId`=iApplyUserId and `ToUserId`=iToUserId limit 1;
set oData = 1;
end if;
END
很久以前在做第一版的麻將時發現那位服務端非常喜歡用存儲過程, 可能是因為服務端 nodejs 且沒有做數據持久化的緣故, 很多數據無法獲取必須重新拉數據, 這樣就會造成數據庫壓力很大, 最早接手開發RPG遊戲時必然是必須做數據持久化的, 設計到服務端乘載人數跟架構, 不做數據持久化管理壓力會壓在Mysql上, 後來做博奕遊戲就很少做這塊了, 輕便為主