集算器提供了 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
来源:oschina
链接:https://my.oschina.net/u/4413367/blog/3226257