集算器提供了 ODBC 接口,C# 可以通過集算器 ODBC 調用 SPL。結構圖如下:
ODBC 服務
安裝集算器 ODBC 驅動
使用集算器 ODBC,首先客戶端需要安裝 ODBC 驅動,在集算器安裝路徑下的 bin 目錄中,用管理員權限執行 esprocOdbcinst.exe,即可安裝集算器 ODBC 的驅動程序。
啓動 ODBC 服務
在集算器的 [安裝根目錄]\esProc\bin 中,雙擊 esprocs.exe 文件(在 Linux 系統中,可以運行 ServerConsole.sh 來啓動服務窗口),彈出如下服務窗口:
選擇 Odbc Server ,點擊【Config】按鈕,可以打開集算器 ODBC 服務窗口如下:
ODBC 服務配置中主要配置 IP、ODBC 服務的端口、允許訪問的用戶名和密碼。配置完成後,點擊【OK】,保存配置。然後點擊【start】啓動服務。
添加 ODBC 數據源
驅動程序安裝成功後,可以添加對應的 ODBC 數據源,選擇 EsprocOdbc ODBC Driver
在彈出的配置窗口中,配置集算器 ODBC 的連接參數,數據源名稱用戶可自定義,IP、端口、用戶名密碼等參數要與服務器中的配置一致,如:
點擊 Connect Test 可以測試連接,如果配置正確,會顯示測試連接成功:
C# 調用
執行 SPL 語句
比如創建一個數據表,並添加兩個字段 baseNum、square2,分別將 100 以內的自然數及其的平方值組成 100 條記錄插入到數據表中,最後將表中的數據作爲結果集返回。
C# 代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.ComponentModel; using System.Text; using System.Data.Odbc; namespace ODBCtest { classDB { publicvoid rset(OdbcConnectionconn, string selectSql) { OdbcCommandcmd = newOdbcCommand(selectSql, conn); OdbcDataReader reader = cmd.ExecuteReader(); int nCount = 0; //循環輸出列名 for (int i=0; i< reader.FieldCount;i++) { Console.Write( reader.GetName(i) + "\\t"); } Console.Write("\\n"); while (reader.Read()) { Console.Write(reader.GetInt32(0) + "\t"); Console.WriteLine(reader.GetInt32(1) + "\\t"); nCount++; } Console.WriteLine("while end column="\+ reader.FieldCount); Console.WriteLine("while end row=" \+ nCount); } } classProgram { staticvoid Main(string\[\] args) { //生成ODBC連接字符串,其中DSN、UID、PWD屬性依次表示ODBC數據源名稱、用戶名、密碼 stringconstr = "DSN=EsprocOdbc;"\+ "UID=user0;"\+ "PWD=123;"; OdbcConnectionconn = newOdbcConnection(constr); conn.Open(); //要執行的SPL語句 stringspl = "10.new(~:baseNum,~*~:square2)"; DBdb = newDB(); db.rset(conn, spl); Console.Write("end...."); Console.ReadKey(); conn.Close(); } } }using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.ComponentModel; using System.Text; using System.Data.Odbc; namespace ODBCtest { classDB {publicvoid rset(OdbcConnectionconn, string selectSql) { OdbcCommandcmd = newOdbcCommand(selectSql, conn); OdbcDataReader reader = cmd.ExecuteReader();int nCount = 0;//循環輸出列名for (int i=0; i< reader.FieldCount;i++) { Console.Write( reader.GetName(i) + "\\t"); } Console.Write("\\n");while (reader.Read()) { Console.Write(reader.GetInt32(0) + "\t"); Console.WriteLine(reader.GetInt32(1) + "\\t"); nCount++; } Console.WriteLine("while end column="\+ reader.FieldCount); Console.WriteLine("while end row=" \+ nCount); } } classProgram {staticvoid Main(string\[\] args) {//生成ODBC連接字符串,其中DSN、UID、PWD屬性依次表示ODBC數據源名稱、用戶名、密碼stringconstr = "DSN=EsprocOdbc;"\+ "UID=user0;"\+ "PWD=123;"; OdbcConnectionconn = newOdbcConnection(constr); conn.Open();//要執行的SPL語句stringspl = "10.new(~:baseNum,~*~:square2)"; DBdb = newDB(); db.rset(conn, spl); Console.Write("end...."); Console.ReadKey(); conn.Close(); } } }
執行結果:
在 SPL 中訪問本地文件
通過 SPL 還可以訪問本地的文件,其中包括 Txt、Excel、Json、Csv、Ctx 等多種類型的文件,訪問時可以通過絕對路徑查文件位置,也可以通過相對路徑查找,使用相對路徑時,則是相對於配置文件中的主目錄,所以,首先我們來配置下主目錄:
在 raqsoftConfig.xml 文件的節點 < Esproc ></ Esproc > 中添加以下節點:
<!--集算器主路徑,該路徑爲單一的絕對路徑--> <mainPath>D:\\mainFile</mainPath> <!--集算器主路徑,該路徑爲單一的絕對路徑--><mainPath>D:\\mainFile</mainPath>
我們把要調用的文件 employee.txt 放到主目錄下面,在 C# 中調用時,建立連接等部分的代碼與上例是完全相同的, SPL 語句部分如下:
stringspl = "=file(\\"employee.txt\\").import@t()";//SPL語句stringspl = "=file(\\"employee.txt\\").import@t()";//SPL語句
這裏支持絕對路徑與相對路徑的使用。
結果集輸出部分代碼如下:
while (reader.Read()) { Console.Write(reader.GetInt32(0) + "\\t"); Console.Write(reader.GetString(1) + "\\t"); Console.Write(reader.GetString(2) + "\\t"); Console.Write(reader.GetString(3) + "\\t"); Console.Write(reader.GetString(4) + "\\t"); Console.Write(reader.GetDate(5).ToString("yyyy-MM-dd") \+ "\\t"); Console.Write(reader.GetDate(6).ToString("yyyy-MM-dd") \+ "\\t"); Console.Write(reader.GetString(7) + "\\t"); Console.WriteLine(reader.GetInt32(8) ); nCount++; }while (reader.Read()) { Console.Write(reader.GetInt32(0) + "\\t"); Console.Write(reader.GetString(1) + "\\t"); Console.Write(reader.GetString(2) + "\\t"); Console.Write(reader.GetString(3) + "\\t"); Console.Write(reader.GetString(4) + "\\t"); Console.Write(reader.GetDate(5).ToString("yyyy-MM-dd") \+ "\\t"); Console.Write(reader.GetDate(6).ToString("yyyy-MM-dd") \+ "\\t"); Console.Write(reader.GetString(7) + "\\t"); Console.WriteLine(reader.GetInt32(8) ); nCount++; }
執行結果:
對於這種簡單運算,還可以使用簡單 SQL 語法:
stringspl = "$select * from employee.txt";stringspl = "$select * from employee.txt";
其中 $ 表示訪問本地文件系統,兩種寫法的結果集相同。
帶參數的 SPL 語句
參數是 SQL 語句的一個重要組成部分,同樣,SPL 語句中也支持參數的使用,例如,像上例中,要查詢 employee.txt 文件中的數據,但是要求只查詢工資在 10000 到 15000 之間的記錄,並根據工資升序排序:
調用部分代碼如下:
stringspl = "$select * from employee.txt where SALARY > ? and SALARY< ? order by SALARY";stringspl = "$select * from employee.txt where SALARY > ? and SALARY< ? order by SALARY";
其中用?表示參數。
rset 方法中的傳參部分代碼如下:
OdbcCommandcmd = newOdbcCommand(selectSql, conn); cmd.Parameters.Add("arg1", OdbcType.Int).Value = 10000; cmd.Parameters.Add("arg2", OdbcType.Int).Value = 15000;OdbcCommandcmd = newOdbcCommand(selectSql, conn); cmd.Parameters.Add("arg1", OdbcType.Int).Value = 10000; cmd.Parameters.Add("arg2", OdbcType.Int).Value = 15000;
執行結果:
有數據源的 SPL 語句
集算器既然是個數據計算工具,那麼數據來源的重要途徑之一就是數據庫了,C# 中如何來調用帶數據源的 SPL 語句呢?往下看:
C# 調用帶數據源的 SPL 語句之前,需要先在應用項目中添加對應的數據庫驅動,然後在配置文件 raqsoftConfig.xml 中配置數據源信息。
例如:調用的 SPL 語句中使用的數據源名稱爲 dm,數據庫類型爲 HSQL,那麼配置如下:
首先,將 HSQL 的數據集驅動 hsqldb.jar 加載到應用項目中;
其次,在 raqsoftConfig.Xml 的 < Runtime ></ Runtime > 節點中配置數據源信息:
<DBList> <DB name="dm"> <!--數據源名稱--> <property name="url" value="jdbc:hsqldb:hsql://127.0.0.1/demo" ></property> <!\-\- url連接--> <property name="driver" value="org.hsqldb.jdbcDriver" ></property> <!--數據庫驅動--> <property name="type" value="13" ></property> <!--數據庫類型--> <property name="user" value="sa" ></property> <!--用戶名--> <property name="password" value=""></property> <!--密碼--> <property name="batchSize" value="1000" ></property> <property name="autoConnect" value="true" ></property> <!--是否自動連接,如果設定爲true,則可以直接以$開頭的SQL語句來訪問數據庫,如果爲false,則不會自動連接,使用前必須用connect(db)語句創建數據庫連接--> <property name="useSchema" value="false" ></property> <property name="addTilde" value="false" ></property> <property name="dbCharset" value="UTF-8" ></property> <property name="clientCharset" value="UTF-8" ></property> <property name="needTransContent" value="false" ></property> <property name="needTransSentence" value="false" ></property> <property name="caseSentence" value="false" ></property> </DB> </DBList><DBList><DB name="dm"><!--數據源名稱--><property name="url" value="jdbc:hsqldb:hsql://127.0.0.1/demo" /> <!\-\- url連接--><property name="driver" value="org.hsqldb.jdbcDriver" /> <!--數據庫驅動--><property name="type" value="13" /><!--數據庫類型--><property name="user" value="sa" /> <!--用戶名--><property name="password" value=""/> <!--密碼--><property name="batchSize" value="1000" /><property name="autoConnect" value="true" /><!--是否自動連接,如果設定爲true,則可以直接以$開頭的SQL語句來訪問數據庫,如果爲false,則不會自動連接,使用前必須用connect(db)語句創建數據庫連接--><property name="useSchema" value="false" /><property name="addTilde" value="false" /><property name="dbCharset" value="UTF-8" /><property name="clientCharset" value="UTF-8" /><property name="needTransContent" value="false" /><property name="needTransSentence" value="false" /><property name="caseSentence" value="false" /></DB></DBList>
現在我們通過 SPL 從 dm 數據源中查詢 SALES 表,過濾出 SELLERID 爲 3 的員工,在 2014 年 11 月 11 號到 2014 年 12 月 12 號期間的所有訂單信息:
調用部分代碼如下:
stringspl = "$(dm)select * from SALES where SELLERID = ? and ORDERDATE>TO\_DATE(?,'YYYY-MM-DD') and ORDERDATE<TO\_DATE(?,'YYYY-MM-DD')";stringspl = "$(dm)select * from SALES where SELLERID = ? and ORDERDATE>TO\_DATE(?,'YYYY-MM-DD') and ORDERDATE<TO\_DATE(?,'YYYY-MM-DD')";
rset 方法中參數傳遞部分代碼如下:
cmd.Parameters.Add("arg1", OdbcType.Int).Value = 3; cmd.Parameters.Add("arg2", OdbcType.Date).Value = "2014-11-11"; cmd.Parameters.Add("arg3", OdbcType.Date).Value = "2014-12-12"; cmd.Parameters.Add("arg1", OdbcType.Int).Value = 3; cmd.Parameters.Add("arg2", OdbcType.Date).Value = "2014-11-11"; cmd.Parameters.Add("arg3", OdbcType.Date).Value = "2014-12-12";
結果集輸出部分代碼如下:
while (reader.Read()) { Console.Write(reader.GetInt32(0) + "\\t"); Console.Write(reader.GetString(1) + "\\t"); Console.Write(reader.GetInt32(2) + "\\t"); Console.Write(reader.GetDecimal(3) + "\\t"); Console.WriteLine(reader.GetDateTime(4).ToString("yyyy-MM-dd HH