oracle資料庫同步,100萬資料秒級插入
近期為了滿足客戶的(××電網公司)需求,先說下他們的需求,需求如下:
1.實現Ⅱ區、Ⅲ區資料庫的同步,其中Ⅱ區是主資料庫,Ⅲ區是需要同步的資料庫。
2.兩臺資料庫伺服器之間是不能直接通訊的,因為Ⅱ、Ⅲ區之間安裝了隔離裝置,只能通過埠訪問。
3.同步需要保證實時性,資料都是秒級的,一分鐘下來至少是2萬條資料。
看到這個需求我的第一反應估計跟大家是一樣的,就是建立外連線,然後使用merger函式去定時同步,效果是最好的,但最終只能想想了,因為兩臺伺服器根本不能通訊的。
上面的方法行不通了就得換一種方式了,後面經過和同事們討論定下了一個方案,思路如下:
1.使用儲存過程生成更新的或者插入的SQL語句,儲存到表中;
2.使用後臺服務定期讀取表中已經生成好的SQL語句做成bat檔案並壓縮打包;
3.使用傳輸服務將Ⅱ區的檔案傳輸到Ⅲ區指定伺服器並解壓到指定的目錄;
4.使用Ⅲ區的同步服務呼叫bat檔案進行資料插入
思路是沒問題的,基本功能都實現了,但是問題就處在效率提不上去,同步2萬資料需要一分鐘以上,這顯然是不符合需求的。
行不通就只能換一個方案了,不使用批處理來同步了,先程式碼來實現同步;
詳細思路如下:
1.同樣是使用儲存過程生成指定格式的字串(XML格式)儲存到資料庫中,程式碼如下:
1)既然是指定格式的話,肯定要模版才行,下面的程式碼是根據配置生成指定格式的模版
create or replace procedure P_pub_SyncData_InitTemplate is
/*
過程名稱:P_pub_SyncData_InitTemplate
用途:資料庫同步,生成模版
建立日期:2013-07-03 16:41:00
*/
V_INSERT_TEMPLATE VARCHAR2(2000);
V_INSERT_TEMPLATE_COL VARCHAR2(1000);
V_INSERT_TEMPLATE_VAL VARCHAR2(1000);
V_DELETE_TEMPLATE VARCHAR2(1000);
V_DATA_XMLTEMPLATE VARCHAR2(2000);
V_DATA_TYPETEMPLATE VARCHAR2(2000);
V_DELETE_COND_TEMPLATE VARCHAR2(500);
V_COL_LIST dbms_sql.Varchar2_Table; --欄位集合
V_COL_TYPE_LIST dbms_sql.Varchar2_Table; --欄位型別集合
CURSOR C_SYNC_CFG IS
SELECT upper(TABLE_NAME) TABLE_NAME,
upper(DELETE_CONDITION) DELETE_CONDITION,
upper(COMPARE_DATE_COL) COMPARE_DATE_COL ,
EXEC_TYPE,
SYNCTIME_TYPE,
TIMETAG_TYPE
FROM TB_PUB_SYNC_DATA_CFG_NEW;
begin
FOR V_SYNC IN C_SYNC_CFG LOOP
SELECT COLUMN_NAME,DATA_TYPE bulk collect into V_COL_LIST,V_COL_TYPE_LIST from USER_TAB_COLUMNS where table_name=V_SYNC.TABLE_NAME;
--資料插入 欄位
V_INSERT_TEMPLATE_COL := 'INSERT INTO '|| V_SYNC.TABLE_NAME||'(';
--資料插入 值
V_INSERT_TEMPLATE_VAL := ' VALUES(';
--如果是 是先清空表中的資料 使用truncate 提高效率
IF V_SYNC.EXEC_TYPE=1 THEN
V_DELETE_TEMPLATE :='TRUNCATE TABLE '||V_SYNC.TABLE_NAME;
ELSE
--刪除模版
V_DELETE_TEMPLATE :='DELETE '||V_SYNC.TABLE_NAME||' WHERE 1=1 ';
END IF;
--XML中的資料行模版
V_DATA_XMLTEMPLATE :='SELECT ''<'||V_SYNC.TABLE_NAME||'DataRow ';
--表格 列的資料型別模版
V_DATA_TYPETEMPLATE :='<'||V_SYNC.TABLE_NAME||'Coltype';
--資料刪除時 條件列模版
V_DELETE_COND_TEMPLATE:='<'||V_SYNC.TABLE_NAME||'DelCol DeleteCol="'||V_SYNC.DELETE_CONDITION||'"></'||V_SYNC.TABLE_NAME||'DelCol>';
FOR I IN 1..V_COL_LIST.COUNT LOOP
V_INSERT_TEMPLATE_COL :=V_INSERT_TEMPLATE_COL||V_COL_LIST(I)||',';
V_INSERT_TEMPLATE_VAL :=V_INSERT_TEMPLATE_VAL||':'||V_COL_LIST(I)||',';
V_DATA_TYPETEMPLATE :=V_DATA_TYPETEMPLATE||' '||V_COL_LIST(I)||'="'||initcap(V_COL_TYPE_LIST(I))||'"';
V_DATA_XMLTEMPLATE :=V_DATA_XMLTEMPLATE ||' '||V_COL_LIST(I)||'="'||FUN_PUB_SYNC_TEMPLATE_FORMAT(V_COL_LIST(I),V_COL_TYPE_LIST(I))||'"';
IF V_SYNC.EXEC_TYPE=0 AND INSTR(V_SYNC.DELETE_CONDITION,V_COL_LIST(I))>0 THEN
V_DELETE_TEMPLATE :=V_DELETE_TEMPLATE||' AND '||V_COL_LIST(I)||'=:'||V_COL_LIST(I);
END IF;
END LOOP;
V_INSERT_TEMPLATE :=substr(V_INSERT_TEMPLATE_COL,0,length(V_INSERT_TEMPLATE_COL)-1)||') '||substr(V_INSERT_TEMPLATE_VAL,0,length(V_INSERT_TEMPLATE_VAL)-1)||')';
V_DATA_TYPETEMPLATE :=V_DATA_TYPETEMPLATE||'></'||V_SYNC.TABLE_NAME||'Coltype>';
V_DATA_XMLTEMPLATE :=V_DATA_XMLTEMPLATE||'></'||V_SYNC.TABLE_NAME||'DataRow>'' FROM '||V_SYNC.TABLE_NAME||' WHERE 1=1';
--生成查詢條件模版
--不區分機組
IF V_SYNC.TIMETAG_TYPE=1 AND V_SYNC.COMPARE_DATE_COL IS NOT NULL then
V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND '||V_SYNC.COMPARE_DATE_COL|| '>{BEGIN_DATE} AND '||V_SYNC.COMPARE_DATE_COL||'<={END_DATE}';
--區分機組
ELSIF V_SYNC.TIMETAG_TYPE=0 AND V_SYNC.COMPARE_DATE_COL IS NOT NULL THEN
V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND '||V_SYNC.COMPARE_DATE_COL|| '>{BEGIN_DATE} AND '||V_SYNC.COMPARE_DATE_COL||'<={END_DATE} AND SET_CODE={SET_CODE} AND FACTORY_CODE={FACTORY_CODE}';
ELSIF V_SYNC.TIMETAG_TYPE=0 THEN
V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND SET_CODE={SET_CODE} AND FACTORY_CODE={FACTORY_CODE}';
END IF;
UPDATE TB_PUB_SYNC_DATA_CFG_NEW SET insert_template=V_INSERT_TEMPLATE,delete_template=V_DELETE_TEMPLATE,DATA_XMLTEMPLATE=V_DATA_XMLTEMPLATE,DELETE_COND_TEMPLATE=V_DELETE_TEMPLATE,DATA_TYPE_TEMPLATE=V_DATA_TYPETEMPLATE WHERE UPPER(TABLE_NAME)=V_SYNC.TABLE_NAME;
END LOOP;
--插入資料更新狀態標籤
MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (select 'SYNCSTATUSTAG' TABLE_NAME FROM DUAL) T1 ON (T.TABLE_NAME=T1.TABLE_NAME)
WHEN NOT MATCHED THEN
INSERT VALUES('SYNCSTATUSTAG','0','0',SYSDATE,SYSDATE,SYSDATE);
COMMIT;
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line(substr(sqlerrm,0,200));
rollback;
end P_pub_SyncData_InitTemplate;
2)根據生成的模版去生成資料,程式碼如下:
create or replace procedure P_PUB_JOB_DATA_SYNC_New
/*
過程名稱:P_JOB_PUB_DATA_SYNC
用途:資料庫同步,生成資料指令碼
建立人:顏顯斌
建立日期:2013-07-03 16:41:00
*/
is
TYPE Mycursor_Type is ref cursor; --遊標型別變數
CUR_SQL Mycursor_Type; --遊標變數
V_SQL VARCHAR2(2000);
V_SYNC_TIME date;
V_FACTORY_CODE_LIST dbms_sql.Varchar2_Table;
V_SET_CODE_LIST dbms_sql.Varchar2_Table;
V_BEGIN_DATE DATE;
V_END_DATE DATE;
V_TEMP_SQL VARCHAR2(2000);
v_orderno integer:=0; --記錄行數
v_count integer;
v_xmltemp varchar2(2000);
v_exectype varchar2(30);
v_commsql varchar2(200);
CURSOR C_DataSyncCfg IS
SELECT upper(TABLE_NAME) TABLE_NAME,
upper(DELETE_CONDITION) DELETE_CONDITION,
upper(COMPARE_DATE_COL) COMPARE_DATE_COL ,
insert_template,
delete_template,
data_xmltemplate,
delete_cond_template,
data_type_template,
sync_type,
IS_SYNC,
EXEC_TYPE,
SYNCTIME_TYPE,
TIMETAG_TYPE,
order_no
FROM TB_PUB_SYNC_DATA_CFG_NEW where is_sync=1;
begin
--為了保證Xml的完整性,當表中還有資料的時候不再插入,等待後臺服務讀取完成再進行寫入
select count(0) into v_count from tb_pub_sync_data_sql;
if v_count>0 then
return;
end if;
--更新同步資料的狀態標籤,0:正在生成資料;1:資料生成完成後臺可以呼叫(目的:保證XML檔案的完整性)
execute immediate 'update TB_PUB_SYNC_TIMESEG_TAG set factory_code=0,set_code=0,begin_time=sysdate,end_time=sysdate,update_time=sysdate where table_name=''SYNCSTATUSTAG''';
--使用繫結變數 公用的插入資料SQL
v_commsql :='INSERT INTO TB_PUB_SYNC_DATA_SQL (table_name, SQL_CONTENT, UDPATE_TIME,ORDER_NO) VALUES (:x,:x,:x,:x)';
--插入Xml頭和根節點
execute immediate v_commsql using '','<?xml version="1.0" encoding="utf-8" ?><XMLROOT>',sysdate,v_orderno;
v_orderno :=v_orderno+1;
--得到配置表中的資訊
for V_DataSyncCfg in C_DataSyncCfg
LOOP
--拼湊程式處理中需要的 執行型別
if V_DataSyncCfg.EXEC_TYPE=1 then
v_exectype := 'TruncateAndInsert';
elsif V_DataSyncCfg.EXEC_TYPE=0 then
v_exectype := 'DeleteAndInsert';
elsif V_DataSyncCfg.EXEC_TYPE=2 then
v_exectype := 'Insert';
else
v_exectype := 'DeleteAndInsert';
end if;
--插入表的模版資訊
v_xmltemp := '<'||V_DataSyncCfg.TABLE_NAME||' InsertTemplate="'||V_DataSyncCfg.insert_template||'" DeleteTemplate="'||V_DataSyncCfg.delete_template||'" OrdernNo="'||V_DataSyncCfg.order_no||'" ExecType="'||v_exectype||'">';
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
v_orderno :=v_orderno+1;
--插入刪除條件模版
v_xmltemp := '<'||V_DataSyncCfg.TABLE_NAME||'DelCol DeleteCol="'||V_DataSyncCfg.DELETE_CONDITION||'"></'||V_DataSyncCfg.TABLE_NAME||'DelCol>';
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
v_orderno :=v_orderno+1;
--插入資料型別模版
v_xmltemp := V_DataSyncCfg.data_type_template;
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
v_orderno :=v_orderno+1;
--時間標籤不區分機組
-------------------------------BEGIN---------------------------------------------------------------------------------
----------------------不區分機組的時間標籤開始----------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
IF V_DataSyncCfg.TIMETAG_TYPE=1 THEN
BEGIN
--獲取上次更新結束時間
BEGIN
SELECT END_TIME INTO V_BEGIN_DATE FROM TB_PUB_SYNC_TIMESEG_TAG WHERE TABLE_NAME=V_DataSyncCfg.TABLE_NAME;
EXCEPTION WHEN NO_DATA_FOUND THEN
V_BEGIN_DATE := SYSDATE-365;
END;
--如果時間型別為系統時間
IF V_DataSyncCfg.SYNCTIME_TYPE=0 THEN
V_END_DATE := SYSDATE;
--如果時間型別為資料時間
ELSE
EXECUTE IMMEDIATE 'SELECT MAX('||V_DataSyncCfg.COMPARE_DATE_COL||') FROM '||V_DataSyncCfg.TABLE_NAME INTO V_END_DATE;
END IF;
IF V_END_DATE IS NULL OR V_END_DATE<=V_BEGIN_DATE THEN
GOTO LABEL_NEXT_TABLE_SYNC;
END IF;
V_TEMP_SQL :=V_DataSyncCfg.data_xmltemplate;
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{BEGIN_DATE}','to_date('''||to_char(V_BEGIN_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{END_DATE}','to_date('''||to_char(V_END_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
--dbms_output.put_line(V_TEMP_SQL);
------------------------------BEGIN----------------------------------------------------------------------------------
----------------------開始執行動態遊標----------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--動態執行模版SQL
OPEN CUR_SQL FOR V_TEMP_SQL;
LOOP
EXIT WHEN CUR_SQL%NOTFOUND;
FETCH CUR_SQL INTO V_SQL;
IF V_SQL IS NOT NULL THEN
--將結果寫入表中
V_SYNC_TIME := SYSDATE;
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,V_SQL,V_SYNC_TIME,v_orderno;
v_orderno :=v_orderno+1;
V_SQL := NULL;
END IF;
END LOOP;
--------------------------------------------------------------------------------------------------------------------
----------------------結束執行動態遊標----------------------------------------------------------------------
---------------------------END--------------------------------------------------------------------------------------
MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (SELECT V_DataSyncCfg.TABLE_NAME TABLE_NAME FROM DUAL) T1
ON (T.TABLE_NAME=T1.TABLE_NAME)
WHEN MATCHED THEN
UPDATE SET END_TIME=V_END_DATE,BEGIN_TIME=V_BEGIN_DATE,UPDATE_TIME=SYSDATE
WHEN NOT MATCHED THEN
INSERT VALUES(V_DataSyncCfg.TABLE_NAME,'','',V_BEGIN_DATE,V_END_DATE,SYSDATE);
END;
--------------------------------------------------------------------------------------------------------------------
----------------------不區分機組的時間標籤結束----------------------------------------------------------
----------------------------END-------------------------------------------------------------------------------
-------------------------------BEGIN-------------------------------------------------------------------------------
----------------------時間標籤區分機組開始----------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--時間標籤區分機組,這種是出現表中沒有UPDATE_TIME的情況下
ELSE
BEGIN
SELECT FACTORY_CODE, SET_CODE BULK COLLECT INTO V_FACTORY_CODE_LIST, V_SET_CODE_LIST FROM V_PUB_SET WHERE IS_VIRTUAL<>1 ORDER BY FACTORY_CODE, SET_CODE desc;
----------------------------BEGIN-----------------------------------------------------------------------------------
----------------------迴圈機組列表開始----------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--迴圈機組列表
FOR I IN 1..V_SET_CODE_LIST.COUNT LOOP
--獲取開始時間
BEGIN
SELECT END_TIME INTO V_BEGIN_DATE FROM TB_PUB_SYNC_TIMESEG_TAG WHERE TABLE_NAME=V_DataSyncCfg.TABLE_NAME AND SET_CODE=V_SET_CODE_LIST(I) AND FACTORY_CODE=V_FACTORY_CODE_LIST(I);
EXCEPTION WHEN NO_DATA_FOUND THEN
V_BEGIN_DATE := SYSDATE-365;
WHEN OTHERS THEN
GOTO LABEL_NEXT_SET;
END;
--如果時間型別為系統時間
IF V_DataSyncCfg.SYNCTIME_TYPE=0 THEN
V_END_DATE := SYSDATE;
--如果時間型別為資料時間
ELSE
BEGIN
EXECUTE IMMEDIATE 'SELECT MAX('||V_DataSyncCfg.COMPARE_DATE_COL||') FROM '||V_DataSyncCfg.TABLE_NAME||' WHERE SET_CODE='||V_SET_CODE_LIST(I)||'
AND FACTORY_CODE='''||V_FACTORY_CODE_LIST(I)||'''' INTO V_END_DATE;
EXCEPTION WHEN OTHERS THEN
GOTO LABEL_NEXT_SET;
END;
END IF;
IF V_END_DATE IS NULL OR V_END_DATE<=V_BEGIN_DATE THEN
GOTO LABEL_NEXT_SET;
END IF;
V_TEMP_SQL :=V_DataSyncCfg.data_xmltemplate;
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{BEGIN_DATE}','to_date('''||to_char(V_BEGIN_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{END_DATE}','to_date('''||to_char(V_END_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{FACTORY_CODE}',''''||V_FACTORY_CODE_LIST(I)||'''');
V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{SET_CODE}',''''||V_SET_CODE_LIST(I)||'''');
--dbms_output.put_line(V_TEMP_SQL);
-------------------------------BEGIN--------------------------------------------------------------------------------
----------------------開始執行動態遊標----------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
--開始執行動態遊標
OPEN CUR_SQL FOR V_TEMP_SQL;
LOOP
EXIT WHEN CUR_SQL%NOTFOUND;
FETCH CUR_SQL INTO V_SQL;
IF V_SQL IS NOT NULL THEN
--將結果寫入表中
V_SYNC_TIME := SYSDATE;
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,V_SQL,V_SYNC_TIME,v_orderno;
v_orderno :=v_orderno+1;
V_SQL := NULL;
END IF;
END LOOP;
--------------------------------------------------------------------------------------------------------------------
----------------------結束執行動態遊標----------------------------------------------------------------------
-----------------------------END------------------------------------------------------------------------------------
MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (SELECT V_DataSyncCfg.TABLE_NAME TABLE_NAME,V_FACTORY_CODE_LIST(I) FACTORY_CODE,V_SET_CODE_LIST(I) SET_CODE FROM DUAL) T1
ON (T.TABLE_NAME=T1.TABLE_NAME AND T.FACTORY_CODE=T1.FACTORY_CODE AND T.SET_CODE=T1.SET_CODE)
WHEN MATCHED THEN
UPDATE SET END_TIME=V_END_DATE,BEGIN_TIME=V_BEGIN_DATE,UPDATE_TIME=SYSDATE
WHEN NOT MATCHED THEN
INSERT VALUES(V_DataSyncCfg.TABLE_NAME,V_FACTORY_CODE_LIST(I),V_SET_CODE_LIST(I),V_BEGIN_DATE,V_END_DATE,SYSDATE);
--每個機組提交一次
<<LABEL_NEXT_SET>>
NULL;
END LOOP;
--------------------------------------------------------------------------------------------------------------------
----------------------迴圈機組列表結束----------------------------------------------------------------------
-----------------------------END-----------------------------------------------------------------------------------
END;
END IF;
--------------------------------------------------------------------------------------------------------------------
----------------------時間標籤區分機組結束----------------------------------------------------------
------------------------------END-----------------------------------------------------------------------------------
--插入表接點結束符
execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,'</'||V_DataSyncCfg.TABLE_NAME||'>',sysdate,v_orderno;
v_orderno:=v_orderno+1;
--如果是手動同步,則同步一次即修改同步標識,標識為不同步
IF V_DataSyncCfg.SYNC_TYPE=0 AND V_DataSyncCfg.IS_SYNC=1 THEN
UPDATE TB_PUB_SYNC_DATA_CFG_NEW SET IS_SYNC=0 WHERE upper(TABLE_NAME)=upper(V_DataSyncCfg.TABLE_NAME);
END IF;
<<LABEL_NEXT_TABLE_SYNC>>
null;
END LOOP;
--插入根節點結束符
execute immediate v_commsql using '','</XMLROOT>',sysdate,v_orderno;
--更新資料同步狀態為‘1’已完成,這時後臺服務可以呼叫
execute immediate 'update TB_PUB_SYNC_TIMESEG_TAG set factory_code=1,set_code=1,begin_time=sysdate,end_time=sysdate,update_time=sysdate where table_name=''SYNCSTATUSTAG''';
COMMIT;
EXCEPTION WHEN OTHERS THEN
ROLLBACK;
END P_PUB_JOB_DATA_SYNC_New;
上面列出的就是資料庫的兩個核心儲存過程,使用job定時去執行P_PUB_JOB_DATA_SYNC_New
然後使用查詢是,用tb_pub_sync_data_sql表中的order_no欄位 排序,這樣能保證XML的完整性
3)使用後臺服務定時讀取tb_pub_sync_data_sql中的資料去生成檔案,生成的檔案格式如下:
<?xml version="1.0" encoding="utf-8" ?>
<XMLROOT>
--該節點儲存表的插入和刪除模版以及更新方式
<表名 InsertTemplate="" DelteTemplate="" ExecType="" Order_No="">
--該節點儲存,刪除時需要用那些欄位來做條件,多個欄位用逗號隔開,該節點每張表只會寫一次
<表名DelCol DeleteCol="col1,col2,col3"></表名DelCol DelCol>
--該節點儲存表中各欄位的資料型別,用於程式進行資料轉換,該節點每張表只會寫一次
<表名ColType col1="Varchar2" col2="Number" col3="Varchar2"></表名ColType>
--該節點用於儲存資料,一條資料對應一個節點
<表名DataRow col1="12" col2="23" col3="45"></表名DataRow>
</表名>
</XMLROOT>
3)將檔案壓縮打包,然後通過傳輸服務將檔案傳送到Ⅲ區伺服器指定的目錄
4)Ⅲ區伺服器上的資料同步服務,讀取指定目錄下的XML檔案進行解析,轉換成目標格式,下面貼出主要的程式碼
程式碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataSyncSvr.DataEntity;
using Oracle.DataAccess.Client;
using DataSyncSvr.DataParse;
using Publish.Log;
using System.IO;
using System.Data;
namespace DataSyncSvr
{
public class DataSyncMain
{
public ILogger mlog;
private OracleConnection conn;
public void DataSyncStart()
{
ParseXmlToDataEntity ParseEntity = new ParseXmlToDataEntity();
Dictionary<string, Dictionary<string, DataSyncDataEntity>> FileList = ParseEntity.GetDataEnetityList();
Dictionary<string, DataSyncDataEntity> EntityDataList;
conn = new OracleConnection(SyncConst.Connstr);
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
DataSyncDataEntity EntityData;
if (FileList == null || FileList.Keys.Count < 1) return;
foreach(string filekey in FileList.Keys)
{
EntityDataList=FileList[filekey];
foreach (string key in EntityDataList.Keys)
{
try
{
EntityData = EntityDataList[key];
mlog.LogInfo("開始同步表:\"" + key + "\"");
if (EntityData.ExecuteType == ExecType.DeleteAndInsert || EntityData.ExecuteType == ExecType.TruncateAndInsert)
{
//先執行刪除操作
AddExecParamAndRun(EntityData, ExecType.Delete);
//再執行插入操作
AddExecParamAndRun(EntityData, ExecType.Insert);
}
else
{
AddExecParamAndRun(EntityData, ExecType.Insert);
}
mlog.LogInfo("\"" + key + "\"表資料同步完成,受影響行數:(" + EntityData.RecordCount + ")行");
}
catch (Exception ex)
{
mlog.LogInfo(ex.ToString());
break;
}
}
//刪除檔案
if (File.Exists(filekey))
{
File.Delete(filekey);
mlog.LogInfo("檔案:\"" + filekey + "\"已刪除");
}
}
conn.Close();
}
private void AddExecParamAndRun(DataSyncDataEntity EntityData, ExecType excutetype)
{
OracleParameter Param;
string[] columns = EntityData.InsertCol;
string ExecTemplate = EntityData.InsertTemplate;
if (excutetype.Equals(ExecType.Delete))
{
columns = EntityData.DeleteCol;
ExecTemplate = EntityData.DeleteTemplate;
}
OracleCommand command = new OracleCommand();
command.Connection = conn;
command.CommandText = ExecTemplate;
command.ArrayBindCount = EntityData.TableData[EntityData.InsertCol[0]].Length;
command.CommandTimeout = 600;
if (columns != null && columns.Length > 0)
{
foreach (string colname in columns)
{
if (!string.IsNullOrEmpty(colname))
{
Param = new OracleParameter(colname, EntityData.DataType[colname]);
Param.Direction = ParameterDirection.Input;
Param.Value = EntityData.TableData[colname];
command.Parameters.Add(Param);
}
}
}
command.ExecuteNonQuery();
}
}
}
注意:使用了Oracle.DataAccess.dll動態庫,這個可以去官網下載。
獻醜了,嘿嘿!
QQ:936052556;Email:[email protected]或者QQ郵箱也行