.NET Data Provider 是.NET Framework 编程环境下的数据库用户访问数据库的编程接口,用于连接到数据库、执行命令和检索结果。在数据源和代码之间创建了一个最小层,以便在不以功能为代价的前提下提高性能。
5.1 数据类型
.NET Framework 在 System.Data.DbType 中定义了.NET Framework 数据提供程序的字段、属性或 Parameter 对象的数据类型。DmProvider 数据类型就是 Dm.DmDbType 中定义的数据类型。
DbType 类型 | DmProvider 类型 | DbType 类型 | DmProvider 类型 |
---|---|---|---|
AnsiString | VarChar | Int32 | Int32 |
AnsiStringFixedLength | VarChar | Int64 | Int64 |
Binary | Binary | Object | Blob |
Boolean | Bit | SByte | SByte |
Byte | Byte | Single | Float |
Currency | Decimal | String | VarChar |
Date | Date | StringFixedLength | Char |
DateTime | DateTime | Time | Time |
Decimal | Decimal | UInt16 | UInt16 |
Double | Double | UInt32 | UInt32 |
Guid | VarChar | UInt64 | UInt64 |
Int16 | Int16 | VarNumeric | XDEC |
DM 建表语句类型 | .NET 中对应的类型 | DM 建表语句类型 | .NET 中对应的类型 |
---|---|---|---|
CHAR | typeof(String) | DOUBLE | typeof(Double) |
VARCHAR | typeof(String) | BLOB | typeof(Byte[]) |
BIT | typeof(Boolean) | DATE | typeof(DateTime) |
TINYINT | typeof(SByte) | TIME | typeof(DateTime) |
SMALLINT | typeof(Int16) | TIMESTAMP | typeof(DateTime) |
INT | typeof(Int32) | BINARY | typeof(Byte[]) |
BIGINT | typeof(Int64) | VARBINARY | typeof(Byte[]) |
DEC | typeof(Decimal) | CLOB | typeof(String) |
REAL | typeof(Single) | INTERVAL | typeof(Object) |
5.2 提供的对象和接口
DM .NET Provider 接口主要实现了 DmConnection、DmCommand、DmDataAdapter、DmDataReader、DmParameter、DmParameterCollection、DmTransaction、DmCommandBuilder、DmConnectionStringBuilder、DmClob 和 DmBlob 共 11 个对象。
5.2.1 DmConnection 对象
DmConnection 对象表示一个 DM 数据库打开的连接。
公共属性
ConnectionString:获取或设置用于连接 DM 数据库的字符串;
ConnectionTimeout:获取在尝试建立连接时终止尝试并生成错误之前所等待的时间;
Database:获取要连接的数据库实例名称;
DataSource:获取要连接的数据库服务器名称;
ServerVersion:获取要连接的数据库服务器版本号;
State:获取连接的当前状态;
MppType:MPP 连接属性,有效值为 DmMppType.LOGIN_MPP_LOCAL、DmMppType.LOGIN_MPP_GLOBAL。
公共方法
DmConnection():构造函数,初始化 DmConnection 的新实例;
DmConnection(string connectionString):构造函数,以指定的连接串进行连接对象新实例的初始化;
BeginTransaction():开始数据库事务;
BeginTransaction(IsolationLevel il):以指定的隔离级别启动数据库事务;
ChangeDatabase():DM8 不支持该操作,调用该函数将不产生任何影响;
Close():关闭与数据库的连接;
CreateCommand():创建并返回一个与 DM 关联的 DmCommand 对象;
GetSchema():返回 DM 的数据源的全部元信息;
GetSchema(String) :使用指定字符串的元信息名称返回 DM 元信息结果集;
GetSchema(String, String[]):使用指定字符串的元信息名以及表示限制值的指定字符串数组返回 DM 元信息结果集;
DmStruct CreateStruct(string typeName, object[] attributes):创建并返回一个 DmStruct 对象;
Open():使用 ConnectionString)所指定的属性设置打开数据库连接。
连接串
公共属性 ConnectionString 是用于连接 DM 数据库的字符串,其格式为:
<属性名>=<属性值>{;<属性名>=<属性值>}
其中支持的属性名及其意义如下表所示:
属性名 | 意义 |
---|---|
server | 登录地址。有三种书写方式: 1.使用 IP 地址,例如:192.168.1.24。 2.使用服务名,例如:dmrw。服务名在 dm_svc.conf 文件中配置。 3.使用多个 IP 地址,例如:(192.168.1.24:5236,192.168.1.24:5237) |
login_mode | 在主备情况下是否仅登录到主库或备库。取值范围 0~3;0:主库不存在的情况下可连接备库;1:只连接主库;2:只连接备库;3:优先连接备库。缺省为 0 |
port | 登录端口号。在 server 中没有指定端口号的时候使用 |
user | 用户名 |
password | 用户口令 |
timeout | 连接超时时间,单位毫秒,缺省为 5000;与 connectionTimeout 互为同义词 |
connectionTimeout | 连接超时时间,单位毫秒,缺省为 5000;与 timeout 互为同义词 |
commandTimeout | 命令超时时间,单位秒,0 表示无限制,缺省为 0 |
appname | 应用名 |
primary_key | 需要加双引号的关键字 |
switch_time | 主备切换的次数,缺省为 1 |
switch_interval | 主备切换的时间间隔,单位毫秒,缺省为 1000 |
time_zone | 时区,默认为当前时区 |
rw_separate | 是否使用读写分离系统。0:不启用;1:启用;4:启用,且备库由客户端进行选择,只连接事务一致性备库;缺省为 0 |
rw_percent | 读写分离百分比,缺省为 25 |
connPooling | 是否使用连接缓存池,缺省为 FALSE |
connPoolSize | 连接池中最大连接数,缺省为 100,连接池开启时有效 该配置项与性能强相关,建议在性能敏感的应用中开启 |
connPoolCheck | 是否检查连接池中连接的有效性,TRUE 表示检查, FALSE 表示不检查,缺省为 FALSE,连接池开启时有效 |
connPoolIdleClearInterval | 回收连接池中过期连接的时间间隔,单位毫秒,缺省为 10000 |
connPoolIdleExpiredTime | 连接池中连接的过期时间,单位毫秒,缺省为 0,表示永不过期 |
stmtPooling | 是否启用句柄重用,缺省为 TRUE |
poolSize | 句柄重用缓冲区的大小,缺省为 100 |
logLevel | 日志等级,缺省为 OFF,高级别同时记录低级别的信息。 OFF:不记录; ERROR:记录错误日志; SQL:记录执行 SQL 信息; INFO:记录全部执行信息 |
logDir | 生成日志的文件夹路径,例如”logDir=C:\Users\dameng\Desktop;”,缺省为当前执行程序路径,日志文件名自动生成,格式为”DmProvider_当前日期时间(精确到毫秒).log”,例如: DmProvider_2023_10_17_14_57_10.201.log。 日志文件的绝对路径格式样例为:”C:\Users\dameng\Desktop\DmProvider_2019_09_05_16_49_20.845.log” |
enRsCache | 是否打开结果集缓存。缺省为 false |
rsCacheSize | 缓存池大小,单位 MB。缺省为 10 |
rsRefreshFreq | 缓存池中结果集更新的频率阈值,即大于该值时才检查命中的结果集是否需要更新,单位秒。缺省为 10 |
lobMode | 结果集中大字段类型数据的缓存方式。值为 1 表示本地只缓存一部分数据;值为 2 表示本地缓存全部的数据。缺省为 1 |
batchType | 绑定多行参数执行时,值为 0 表示分多次执行,一次只执行一行参数;值为 1 表示一次执行多行参数。缺省为 1 |
batchNotOnCall | 执行 SQL 为存储过程时,是否允许一次执行多行参数。缺省为 false |
batchContinueOnError | 绑定多行参数执行时,某行参数执行出错后,后续参数是否继续执行。缺省为 false |
batchAllowMaxErrors | 绑定多行参数执行时允许的错误数最大值。缺省为 0 |
bufPrefetch | Fetch 获取的结果集内存大小,单位 MB。缺省为 0 |
compatibleMode | 兼容其他数据库。取值为数据库名称:oracle 表示兼容 Oracle,mysql 表示兼容 Mysql,sqlserver 表示兼容 SQLserver。本参数和 DM.INI 中的 COMPATIBLE_MODE 同名,但用途不同 |
isBdtaRS | 消息中结果集是否以 Bdta 格式。缺省为 false |
maxRows | 返回的结果集最大行数。缺省为 0x7fffffff |
scoketTimeout | 网络包读写的超时时间值,单位秒。缺省为 0 |
addressRemap | 服务器网络地址映射表。默认值为空串。值格式:address_remap=192.168.1.24:5236,192.168.1.23:5236 |
userRemap | 用户名映射表。缺省值为空串。格式同 addressRemap |
epSelector | 服务名配置的集群选取起始位置的方式。值为 0 表示随机选取一个站点为起始位置;值为 1 表示第一个站点就是起始位置。缺省值为 0 |
loginStatus | 设置连接的服务器状态。取值范围 0、3~5;值为 0,表示不开启该功能;值为 4 表示 open 状态;值为 3 表示 mount 状态;值为 5 表示 suspend 状态。缺省值为 0 |
ep_selection | 当集群中存在故障节点时是否进行连接优化。值为 0 表示进行优化,重排连接节点次序,故障节点位置靠后;值为 1 表示不进行优化。缺省为 0 |
maxLobDataLenPerMsg | 指定单条消息中大字段类型数据的最大长度,单位字节,缺省值为 32000,最小值为 1024(1KB),最大值为 104857600(100MB),超出范围则使用默认值 |
dbTimeToTimeSpan | 指定将数据库中的何种类型映射到.NET 的 TimeSpan 类型。TRUE 表示将数据库的 TIME 类型映射到.NET 的 TimeSpan 类型;FALSE 表示将数据库的 INTERVAL DAY(2) TO SECOND(6)类型映射到.NET 的 TimeSpan 类型;缺省值为 FALSE |
caseSensitive | 表示 dmBulkCopy 指定的表名和列名大小写是否敏感。TRUE 表示敏感;FALSE 表示不敏感。缺省值为 FALSE |
varchar36ToGuid | 表示是否将数据库 varchar(36)列类型返回.net Guid 类型。TRUE 表示返回.net Guid 类型;FALSE 表示返回.net string 类型;缺省为 FALSE |
language | 指定驱动本地语言类型。0 表示简体中文;1 表示英文;2 表示香港繁体中文;3 表示台湾繁体中文。缺省为 0 |
useSkyWalking | 用于适配 SkyWalking 链路追踪,需与 SkyWalking 服务 和 DmSkyWalkingAgent 项目搭配使用,同时相关 command 对象需使用 DmConnection.CreateCommand()方法创建,或使用 new DmTracingCommand()创建。用户使用前需为项目添加 DmSkyWalkingAgent 的依赖,该配置才会生效。FALSE 表示关闭 SkyWalking 链路追踪;TURE 表示开启 SkyWalking 链路追踪。缺省为 FALSE |
svc_conf_path | 指定 url 属性配置文件所在路径,例如”C:\Users\dameng\Desktop\dm_svc.conf”,Windows 系统默认路径为”C:\Windows\System32\dm_svc.conf”,Linux 系统默认路径为”/etc/dm_svc.conf” |
intervalMode | 当使用 DmDataReader.GetValue 方法获取 DmIntervalYM 或 DmIntervalDT 数据时是否需要将结果转化为另一种格式。缺省为 OFF 模式。 OFF:不转化; YM:将 DmIntervalYM 转化为月的总数,返回 long 值,如“INTERVAL '15-08' YEAR TO MONTH”返回 188; DT:将 DmIntervalDT 转化为 TimeSpan,如“INTERVAL '09 09:20:01.012345' DAY(2) TO SECOND(6)”转化为“9.09:20:01.0123450”; ALL:同时开启 YM 和 DT 模式 |
sslKeyPass | ssl 证书文件的密码 |
sslFilesPath | ssl 证书文件的地址 |
convertToTz | 用于 DmDateReader.getValue 时确定数据库 DATETIME WITH TIME ZONE 映射。取值 TRUE 或 FALSE,TRUE 表示将 DATETIME WITH TIME ZONE 映射成 DATETIME OFFSET;FALSE 表示将 DATETIME WITH TIME ZONE 映射成 DATETIME。缺省值为 FALSE |
schemaSensitive | 表示指定的 schema 值大小写是否敏感。TRUE 表示敏感;FALSE 表示不敏感。缺省值为 FALSE |
DBAPassword | SYSDBA 用户密码,用于 EFCore 框架创建具有 DBA 权限的连接,进而实现 EnsureDeleted 和 EnsureCreated 功能,若不配置则无法使用相关功能 |
5.2.2 DmCommand 对象
表示要对 DM 数据库执行的一个 Transact-SQL 语句或存储过程。
公共属性
CommandText:获取或设置要对数据源执行的 Transact-SQL 语句或存储过程;
CommandTimeout:获取或设置在终止执行命令的尝试并生成错误之前的等待时间;
CommandType:获取或设置一个值,该值指示如何解释 CommandText 属性;
Connection:获取或设置 DmCommand 的此实例使用的 DmConnection;
Parameters:获取 DmParameterCollection;
Transaction:获取或设置将在其中执行 DmCommand 的 DmTransaction;
UpdatedRowSource:获取或设置命令结果在由 DbDataAdapter 的 Update 方法使用时如何应用于 DataRow。
公共方法
DmCommand():构造函数,初始化 DmCommand 的新实例;
Cancel():试图取消 DmCommand 的执行;
CreateParameter():创建 DmParameter 对象的新实例;
ExecuteNonQuery():对连接执行 Transact-SQL 语句并返回受影响的行数;
ExecuteReader():将 CommandText 发送到 Connection 并生成一个 DmDataReader;
ExecuteReader(CommandBehavior):以指定方式执行 CommandText;
ExecuteScalar():执行查询,并返回查询所返回的结果集中第一行的第一列。忽略额外的列或行;
Prepare():在 DM 的实例上创建命令的一个准备版本。
5.2.3 DmDataAdapter 对象
用于填充 DataSet 和更新 DM 数据库的一组数据命令和一个数据库连接。
公共属性
DeleteCommand:获取或设置一个 Transact-SQL 语句或存储过程,以从数据集删除记录;
InsertCommand:获取或设置一个 Transact-SQL 语句或存储过程,以在数据源中插入新记录;
SelectCommand:获取或设置一个 Transact-SQL 语句或存储过程,用于在数据源中选择记录;
UpdateCommand:获取或设置一个 Transact-SQL 语句或存储过程,用于更新数据源中的记录;
TableMappings:获取一个集合,它提供源表和 DataTable 之间的主映射。
公共方法
DmDataAdapter():构造函数,初始化 DmDataAdapter 的新实例;
Fill():在 DataSet 中添加或刷新行以匹配数据源中的行;
FillSchema():将 DataTable 添加到 DataSet 中,并配置架构以匹配数据源中的架构;
Update():为 DataSet 中每个已插入、已更新或已删除的行调用相应的 INSERT、UPDATE 或 DELETE 语句。
5.2.4 DmDataReader 对象
通过只向前方式从结果集中获取行数据。
公共属性
Depth:获取一个值,该值指示当前行的嵌套深度,目前 DM 返回常数 0;
FieldCount:获取当前行中的列数;
IsClosed:获取一个值,该值指示数据读取器是否已关闭;
RecordsAffected:获取执行 Transact-SQL 语句所更改、插入或删除的行数。
公共方法
Close():关闭 DmDataReader 对象;
GetBoolean():获取指定列的布尔值形式的值;
GetByte():获取指定列的字节形式的值;
GetBytes():从指定的列偏移量将字节流读入缓冲区,并将其作为从给定的缓冲区偏移量开始的数组;
GetChar():获取指定列的单个字符串形式的值;
GetChars():从指定的列偏移量将字符流作为数组从给定的缓冲区偏移量开始读入缓冲区;
GetDataTypeName():获取源数据类型的名称;
GetDateTime():获取指定列的 DateTime 对象形式的值;
GetDecimal():获取指定列的 Decimal 对象形式的值;
GetDouble():获取指定列的双精度浮点数形式的值;
GetEnumerator():返回可循环访问集合的枚举数;
GetFieldType():获取是对象的数据类型的 Type;
GetFloat():获取指定列的单精度浮点数形式的值;
GetInt16():获取指定列的 16 位有符号整数形式的值;
GetInt32():获取指定列的 32 位有符号整数形式的值;
GetInt64():获取指定列的 64 位有符号整数形式的值;
GetKeyCols():获取构成主关键字的列;
GetName():获取指定列的名称;
GetOrdinal():在给定列名称的情况下获取列序号;
GetSchemaTable():返回一个 DataTable,它描述 DmDataReader 的列元数据;
GetString():获取指定列的字符串形式的值;
GetUniqueCols():获取有唯一性约束的列;
GetValue():获取以本机格式表示的指定列的值;
GetValues():获取当前行的集合中的所有属性列;
IsDBNull():获取一个值,该值指示列中是否包含不存在的或缺少的值;
NextResult():当读取批处理 Transact-SQL 语句的结果时,使数据读取器前进到下一个结果;
Read():使 DmDataReader 前进到下一条记录。
5.2.5 DmParameter 对象
表示 DmCommand 的参数以及这些参数各自到 DataSet 中的列的映射。
公共属性
DbType:获取或设置参数的 DbType(兼容 Oracle RefCursor, 使用 DmDbType.RefCursor 进行赋值);
Direction:获取或设置一个值,该值指示参数是只可输入、只可输出、双向还是存储过程返回值参数;
ParameterName:获取或设置 DmParameter 的名称;
Precision:获取或设置用来表示 Value 属性的最大位数;
Scale:获取或设置 Value 解析为的小数位数;
Size:获取或设置列中数据的最大大小;
SourceColumn:获取或设置源列的名称,该源列映射到 DataSet 并用于加载或返回 Value;
SourceVerion:获取或设置在加载 Value 时使用的 DataRowVersion;
Value:获取或设置该参数的值。
公共方法
构造函数,初始化 DmParameter 的新实例:
- DmParameter();
- DmParameter(String parameterName, DmDbType parameterType) ;
- DmParameter(String parameterName, DmDbType parameterType, ParameterDirection direction) ;
- DmParameter(String parameterName, DmDbType parameterType, Int32 size) ;
- DmParameter(String parameterName, DmDbType parameterType, Int32 size, String sourceColumn) ;
- DmParameter(string parameterName, object value)。
5.2.6 DmParameterCollection 对象
表示与 DmCommand 相关的参数集合以及这些参数各自到 DataSet 中的列的映射。
公共属性
Count:获取集合中 DmParameter 对象的数目。
公共方法
Add():将 DmParamter 添加到 DmParameterCollection;
Clear():从集合中移除所有项;
Contains():获取一个值,该值指示集合中是否存在 DmParameter;
CopyTo():将 DmParameter 对象从 DmParameterCollection 复制到指定的数组;
IndexOf():获取 DmParameter 在集合中的位置;
Insert():将 DmParameter 插入到集合中的指定索引位置;
Remove():从集合中移除指定的 DmParameter;
RemoveAt():从集合中移除指定的 DmParameter。
5.2.7 DmTransaction 对象
表示要在 DM 数据库中处理的 Transact-SQL 事务。
公共属性
Connection:获取与该事务关联的 DmConnection 对象;
IsolationLevel:指定该事务的 IsolationLevel。
公共方法
Commit():提交数据库事务;
Dispose():释放由 DmTransaction 占用的非托管资源,还可以释放托管资源;
Rollback():回滚数据库事务;
Save():在事务中创建保存点,并指定保存点名称。
5.2.8 DmCommandBuilder 对象
自动生成用于协调 DataSet 的更改与关联数据库的单表命令。继承自 DbCommandBuilder。
公共属性
ConflictOption:指定 ConflictOption 选项;
QuotePrefix:获取或设置指定其名称包含空格或保留标记等字符的数据库对象(例如,表或列)时使用的开始字符;
QuoteSuffix:获取或设置一个或多个结束字符,供指定其名称中包含空格或保留标记等字符的数据库对象(例如,表或列)时使用。
公共方法
使用继承自 DbCommandBuilder 的公共方法。
5.2.9 DmConnectionStringBuilder 对象
用于对所有连接属性进行解析并保存为 KEY-VALUE 格式。继承自 DbConnectionStringBuilder。
公共属性
使用继承自 DbConnectionStringBuilder 的公共属性。
公共方法
使用继承自 DbConnectionStringBuilder 的公共方法。
5.2.10 DmClob 对象
用于访问服务器的字符类型的大字段对象。
公共属性
无。
公共方法
String GetString(long pos, int length):从 pos 所指定的位置获取个数为 length 字符。pos 从 0 开始计数。如果 length 超过所取字符,则返回实际长度的字符;
long Length():获取大字段的长度;
int SetString(long pos, String str, int offset, int len):从 pos 所指定的位置,更新大字段内容为 str 的内容,offset 为设置 str 的偏移,len 为偏移后设置的字符串长度;pos 从 0 开始计数,若 pos+len<clob.length,即只修改了中间的部分数据时,从 pos+len 到 length 之间的数据不会被删除;
void Truncate(long len):截断大字段为 len 长度;
String GetSubString(long pos, int length):从 pos 所指定的位置,获取长度为 length 的字符串。
5.2.11 DmBlob 对象
用于访问服务器二进制类型大字段。
公共属性
无。
公共方法
long Length():获取大字段数据长度;
int SetBytes(long pos, byte[] bytes, int offset, int len):从 pos 所指定的位置,更新大字段内容为 bytes 的内容,offset 为设置 bytes 的偏移,len 为偏移后设置的字节长度;pos 从 0 开始计数,若 pos+len<blob.length,即只修改了中间的部分数据时,从 pos+len 到 length 之间的数据不会被删除;
byte[] GetBytes(long pos, int length):从 pos 所指定的位置获取 length 个数的字节数据;
void Truncate(long len):将大字段截断为 len 长度;
Stream GetStream():获取流对象,通过流对象进行数据读取;
DmBlob NewInstanceOfLocal(byte[] val, DmConnection connection):创建并返回一个内容为 val 的 DmBlob 对象。connection 为保留参数,不起作用。
5.2.12 DmBulkCopy 对象
用于快速批量装载数据。实现 IDisposable 接口。该功能依赖 DM 安装目录\bin 下的 dmfldr_dll.dll 等动态链接库,需要拷贝到应用程序的执行目录。
公共属性
DestinationTableName:指定目标表名;
ColumnMappings:指定源数据列与目标表列的映射集合;
BatchSize:指定一次发送的数据行数,默认值为 100。
公共方法
void WriteToServer(DataRow[] rows):装载数据;
void WriteToServer(DataRow[] rows, DataColumnCollection columns):装载数据;
void WriteToServer(DataTable table) :装载数据;
void WriteToServer(DataTable table, DataRowState rowState) :装载数据;
void WriteToServer(DbDataReader reader) :装载数据。
5.2.13 DmTracingCommand 对象
用于 SkyWalking 链路追踪,继承自 DmCommand。
公共属性
使用继承自 DmCommand 的公共属性
公共方法
DmTracingCommand():构造函数,初始化 DmTracingCommand 的新实例;
使用继承自 DmCommand 的公共方法
5.3 注册.NET 驱动
有部分场景,使用 DmProvider 时需要注册.NET 驱动,例如通过 DbProviderFactories 类调用 DmProvider 创建连接,NHibernate 及 EFDmProvider 的使用,都需要注册.net 驱动。下面详细介绍下如何注册.NET 驱动。
步骤如下:
1、注册 DmProvider。
gacutil /if E:\dmdbms\drivers\dotNetProvider\DmProvider\DmProvider.dll
2、修改对应框架的配置文件 machine.config。
例如,配置文件 machine.config 目录位于 C:\Program Files\Microsoft Visual Studio10.0\VC>notepad%WINDIR%\Microsoft.NET\Framework\v2.0.50727\config\machine.config。在配置文件 machine.config 中添加以下内容:
...
<!-- Version需要替换为当前DmProvider的版本,否则无法运行程序-->
<DbProviderFactories>
<add description="DM .Net Framework Data Provider" invariant="Dm" name="DM Data Provider" type="Dm.DmClientFactory, DmProvider, Version=8.3.1.24469, Culture=neutral, PublicKeyToken=7a2d44aa446c6d01"/>
</DbProviderFactories>
...
例如,通过 DbProviderFactories 类调用 DmProvider 创建连接使用.NET 驱动的情况。
using System.Data.Common;
...
public static void TestFunc()
{
DbProviderFactory factory = DbProviderFactories.GetFactory("Dm");
DbConnection sconn = factory.CreateConnection();
sconn.ConnectionString = "Server=localhost; UserId=SYSDBA; PWD=sysDBA*00";
sconn.Open();
DbCommand scmd = factory.CreateCommand();
scmd.Connection = sconn;
try
{
scmd.CommandText = "drop table t1 cascade;";
scmd.ExecuteNonQuery();
}
catch (Exception)
{
}
}
5.4 Nhibernate Dm 方言包
DmDialect.dll 是基于 Dm 数据库开发的支持 Nhibernate 的方言包类库,放在 DM 安装目录..\drivers\dotNetProvider\DmDialect 中,方言包程序集名为:DmDialect,Version=1.0.0.0, Culture=neutral, PublicKeyToken=072d25982b139bf8。
Nhibernate Dm 方言包支持 NET Framework,NET Core, NET Standard 框架平台,与 Nhibernate 的版本是保持一致的。
DmDialect.dll 中包含的类有:NHibernate.Driver.DmDriver、NHibernate.Dialect.DmDialect、Nhibernate.Dialect.Schema.DmDataBaseSchema、NHibernate.AdoNet.DmBatchingBatcher 和 NHibernate.AdoNet. DmBatchingBatcherFactory。
下面介绍一下如何使用方言包:
1.添加方言包依赖项。
Nhibernate Dm 方言包依赖项为:DmProvider.dll 和 Nhibernate.dll。
2.应用程序添加依赖项之后,修改 Nhibernate 配置属性。
"dialect": NHibernate.Dialect.DmDialect, DmDialect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=072d25982b139bf8
"connection.driver_class": NHibernate.Driver.DmDriver, DmDialect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=072d25982b139bf8
"connection.connection_string": Server=localhost;UserId=SYSDBA;PWD=sysDBA*00;encoding=utf-8;PORT=5236
5.5 EFDmProvider.EF6 方言包
DM 基于 DmProvider 数据库驱动提供了方言包程序 EFDmProvider.EF6 以支持微软的 EF6(EntityFrameWork)框架。应用程序使用 EF6 连接到 DM 数据库时,不仅需要 DmProvider.dll 和 EFDmProvider.EF6.dll,同时配置文件(默认文件名是 App.config)需满足如下格式:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!--EF6配置类-->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<!--EFDmProvider.EF6配置类,提供一些兼容性配置。若无相关需求则可以注释-->
<section name="EFDm" type="EFDmProvider.config.EFDmConfigurationSection, EFDmProvider.EF6, Version=1.0.0.0, Culture=neutral, PublicKeyToken=514fc861b4bfc6c6" requirePermission="false" />
</configSections>
<!--DmProvider注册,参考驱动注册章节-->
<!-- Version需要替换为当前DmProvider的版本,否则无法运行程序-->
<system.data>
<DbProviderFactories>
<remove invariant="Dm" />
<add description="DM .Net Framework Data Provider" invariant="Dm" name="DM Data Provider" type="Dm.DmClientFactory, DmProvider, Version=8.3.1.24469, Culture=neutral, PublicKeyToken=7a2d44aa446c6d01"/>
</DbProviderFactories>
</system.data>
<!--EF6配置项-->
<entityFramework>
<providers>
<!--- EFDmProvider.EF6提供支持-->
<provider invariantName="Dm" type="EFDmProvider.DmProviderServices, EFDmProvider.EF6" />
</providers>
</entityFramework>
<!--EFDmProvider.EF6配置项,若无相关需求,则可以注释-->
<EFDm>
<!-- varcharMaxToClob标签属性value 为true 表示SqlServer varcharMax类型映射到DM的Clob类型; value为false表示映射到DM的varchar类型。 默认为true-->
<varcharMaxToClob value = "true"/>
</EFDm>
<!--- 连接串配置-->
<connectionStrings>
<add name="VOMEntities" providerName="Dm" connectionString="Server=LOCALHOST;User=USER1;password=USER1;PORT=5236"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
5.6 DM-EFCore 方言包
5.6.1 介绍
EFCore.Dm 程序包是 DM 数据库提供的基于 EFCore 框架连接到 DM 数据库的方言包程序。
5.6.2 使用
EFCore.Dm 方言包位于安装目录..\drivers\dotNet\EFCore.Dm 路径,该程序包依赖 DmProvider 程序和 EFCore 程序,依赖信息在 EFCore.Dm 路径下的 Microsoft.EntityFrameworkCore.Dm.2.1.1.nuspec 文件中可以看到,使用时直接将 EFCore.Dm 程序包及其依赖程序包添加到 nuget 程序包源后,然后在应用程序中添加 nuget 依赖即可。
5.6.3 示例
执行该示例前需要在数据库建表:
create table "Customers"("Id" varchar);
public class CustomerContext : DbContext
{
public CustomerContext(DbContextOptions options):base(options)
{
}
public DbSet<Customer> Customers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>(b =>
{
b.HasKey(c => c.Id);
b.ToTable("Customers");
});
}
}
public class Customer
{
public string Id { get; set; }
}
class Program
{
static void Main(string[] args)
{
try
{
//用户需要在连接串配置中,指定非系统自带SCHEMA,如SCHEMA=TEST(可根据需要自行修改),配合下方context.Database.EnsureCreated(),可自动创建该schema和表
var options = newDbContextOptionsBuilder()
.UseDm("SERVER=localhost;PORT=5236;USER=SYSDBA;PASSWORD=sysDBA*00")
.UseInternalServiceProvider(
newServiceCollection()
.AddEntityFrameworkDm()
.BuildServiceProvider())
.Options;
using (var context = newCustomerContext(options))
{
//受EFCore框架限制,用户需要确保使用的schema下不存在任何对象,才能创建成功
//如果使用系统自带模式(未指定SCHEMA默认为SYSDBA,该模式存在系统对象),导致表创建失败
context.Database.EnsureCreated();
var cus1 = new Customer { Id = "abc"};
var cus2 = new Customer { Id = "qqq" };
context.Customers.AddRange(cus1, cus2);
context.SaveChanges();
var results = context.Customers.Where(c =>c.Id.StartsWith("a"))
.OrderByDescending(c =>c.Id)
.ToList();
Console.WriteLine(results[0].Id);
}
}
catch (Exception e)
{
Console.WriteLine("异常:" + e.Message);
}
Console.WriteLine("test over");
}
}
5.7 对象使用
5.7.1 连接
DM .NET Provider 使用 DMConnection 对象提供与 DM 数据库的连接。DM .NET
Provider 支持连接字符串格式。
例如,指定与本机的 DM 数据库建立连接,用户名为“SYSDBA”,口令为“sysDBA*00”,则代码片断如下。
DmConnection conn = new DmConnection("Server=localhost; User Id=SYSDBA;
PWD=sysDBA*00");
conn.Open();
5.7.1.1 集群连接
DM .NET Provider 支持通过连接字符串和配置 dm_svc.conf 文件的方式配置集群连接,主要包含以下两种方式:
方式一 不使用自定义服务名,直接使用 Server 属性配置集群节点 IP
代码样例:
DmConnection conn = new DmConnection("Server=(192.168.0.1, 192.168.0.2, 192.168.0.3); User Id=SYSDBA; PWD=sysDBA*00");
此时不需要在 dm_svc.conf 文件中配置集群节点的 IP。
方式二 使用自定义服务名,在 dm_svc.conf 文件中配置集群节点 IP
代码样例:
DmConnection conn = new DmConnection("Server=myServer; User Id=SYSDBA;
PWD=sysDBA*00"
dm_svc.conf 文件内容样例:
myServer=(192.168.0.1, 192.168.0.2, 192.168.0.3)
注意,方式二中的集群节点 IP 只能在 dm_svc.conf 文件中配置,不能在连接串中进行配置。
5.7.2 查询与结果集
当建立与数据库的连接后,可以使用 DmCommand 对象来执行命令并从数据库中返回结果。您可以使用 DmCommand 构造函数来创建命令,该构造函数采用在数据源、DmConnection 对象和 DmTransaction 对象中执行的 SQL 语句的可选参数。也可以使用 DmConnection 的 CreateCommand()方法来创建用于特定 DmConnection 对象的命令。您可以使用 DmCommandText 属性来查询和修改 DmCommand 对象的 SQL 语句。
DmCommand 对象公开了几个可用于执行所需操作的 Execute 方法。当以数据流的形式返回结果时,使用 ExecuteReader() 可返回 DataReader
对象。使用 ExecuteScalar() 可返回单个值。使用 ExecuteNonQuery()可执行不返回行的命令。
可以使用 DmDataReader 从数据库中检索只读、只进的数据流。查询结果在查询执行时返回,并存储在客户端的缓冲区中,直到您使用 DmDataReader 的 Read()方法对它们发出请求。
当创建 DmCommand 对象的实例后,可调用 DmCommand.ExecuteReader()从数据源中检索行,从而创建一个 DmDataReader,如以下程序片断所示:
var command = conn.CreateCommand();
command.CommandText = "SELECT NAME, AUTHOR, PUBLISHER FROM
PRODUCTION.PRODUCT;";
var myReader = command.ExecuteReader();
5.7.3 插入、更新、删除
通过 DmCommand 对象的 ExecuteNonQuery 方法可以执行 INSERT 语句来插入数据,C##示例代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using Dm;
namespace DMDemo
{
class InsertDemo
{
//返回结果
static int ret = 1;
static DmConnection cnn = new DmConnection();
[STAThread]
static int Main(string[] args)
{
try
{
cnn.ConnectionString = "Server=localhost; User Id=SYSDBA; PWD=sysDBA*00";
cnn.Open();
InsertDemo demo = new InsertDemo();
demo.TestFunc();
cnn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
return ret;
}
public void TestFunc()
{
var command = cnn.CreateCommand();
try
{
command.CommandText = "INSERT INTO PRODUCTION.PRODUCT(NAME, AUTHOR, PUBLISHER, " +
"PUBLISHTIME, PRODUCT_SUBCATEGORYID, PRODUCTNO, SATETYSTOCKLEVEL, ORIGINALPRICE, " +
"NOWPRICE, DISCOUNT, DESCRIPTION, TYPE, PAPERTOTAL, WORDTOTAL, SELLSTARTTIME, " +
"SELLENDTIME) VALUES ('三国演义', '罗贯中', '中华书局', '2005-04-01', 4, '9787101046121', " +
"10, 19.0000, 15.2000, 8.0, '《三国演义》是中国第一部长篇章回体小说,中国小说" +
"由短篇发展至长篇的原因与说书有关。宋代讲故事的风气盛行,说书成为一种职业,说" +
"书人喜欢拿古代人物的故事作为题材来敷演,而陈寿《三国志》里面的人物众多,事件" +
"纷繁,正是撰写故事的最好素材。三国故事某些零星片段原来在民间也已流传,加上说" +
"书人长期取材,内容越来越丰富,人物形象越来越饱满,最后由许多独立的故事逐渐组" +
"合而成长篇巨著。这些各自孤立的故事在社会上经过漫长时间口耳相传,最后得以加工" +
"、集合成书,成为中国第一部长篇章回体小说,这是一种了不起的集体创造,与由单一" +
"作者撰写完成的小说在形态上有所不同。', '16', 943, 93000, '2006-03-20', '1900-01-01')";
command.ExecuteNonQuery();
string a, b, c;
command.CommandText = "SELECT NAME, AUTHOR, PUBLISHER FROM PRODUCTION.PRODUCT;";
var reader = command.ExecuteReader();
while (reader.Read())
{
a = reader.GetString(0);
b = reader.GetString(1);
c = reader.GetString(2);
Console.WriteLine("NAME:" + a);
Console.WriteLine("AUTHOR:" + b);
Console.WriteLine("PUBLISHER:" + c);
Console.WriteLine("-------------------");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ret = 0;
}
}
}
}
通过 DmCommand 对象的 ExecuteNonQuery 方法可以执行 UPDATE 语句来更新数据,C##示例代码如下:
command.CommandText = "UPDATE PRODUCTION.PRODUCT SET "
+ " NAME = '三国演义(上)' WHERE PRODUCTID = 11";
command.ExecuteNonQuery();
通过 DmCommand 对象的 ExecuteNonQuery 方法可以执行 DELETE 语句来删除数据,C##示例代码如下:
command.CommandText = "DELETE FROM PRODUCTION.PRODUCT WHERE PRODUCTID = 11";
command.ExecuteNonQuery();
5.7.4 大对象
下面的示例将展示读取一张图片到并保存到数据库中。图片以二进制数据存储在 PRODUCT 表中的 PHOTO 字段中。
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Dm;
namespace DMDemo
{
class BinaryDemo
{
//返回结果
static int ret = 1;
static DmConnection cnn = new DmConnection();
[STAThread]
static int Main(string[] args)
{
try
{
cnn.ConnectionString = "Server=localhost; User Id=SYSDBA; PWD=sysDBA*00";
cnn.Open();
BinaryDemo demo = new BinaryDemo();
demo.TestFunc();
cnn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
return ret;
}
public void TestFunc()
{
DmCommand command = new DmCommand();
command.Connection = cnn;
try
{
FileInfo fi = new FileInfo(@"F:\dotnet\dameng\DM数据库例子\三国演义.jpg");
FileStream fs = fi.OpenRead();
int nBytes = (int)fs.Length;
byte[] dataArray = new byte[nBytes];
fs.Read(dataArray, 0, nBytes);
fs.Close();
command.CommandText = "UPDATE PRODUCTION.PRODUCT SET PHOTO = :PHOTO WHERE PRODUCTID = 11";
DmParameter param1 = new DmParameter(":PHOTO", DmDbType.Binary);
command.Parameters.Add(param1);
param1.Value = dataArray;
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ret = 0;
}
}
}
}
5.7.5 自增列
达梦数据库.NET Data Provider 接口支持自增列,如果数据库中的列设置为自增,那么在往数据库中插入记录的时候,不需要给该字段赋值。例如 PRODUCT 表中的 PRODUCTID 字段就设置为自增了,在插入数据时没有给 PRODUCTID 字段赋值,在数据插入达梦数据库时,由数据库根据 PRODUCTID 自增列的设置自动进行赋值。
5.7.6 存储过程与函数
达梦数据库.NET Data Provider 可以使用 DmCommand 对象来执行存储过程与函数。
创建一个存储过程“UPDATEPRODUCT”用来更新表 PRODUCT 中的 NAME 字段,存储过程代码如下:
CREATE OR REPLACE PROCEDURE "PRODUCTION"."UPDATEPRODUCT"
(
V_ID INT,
V_NAME VARCHAR(50)
)
AS
BEGIN
UPDATE PRODUCTION.PRODUCT SET NAME = V_NAME WHERE PRODUCTID = V_ID;
END;
达梦数据库.NET Data Provider 调用存储过程的示例代码如下:
using Dm;
namespace DMDemo
{
class ProcDemo
{
//返回结果
static int ret = 1;
static DmConnection cnn = new DmConnection();
[STAThread]
static int Main(string[] args)
{
try
{
cnn.ConnectionString = "Server=localhost; User Id=SYSDBA; PWD=sysDBA*00";
cnn.Open();
ProcDemo demo = new ProcDemo();
demo.TestFunc();
cnn.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
return ret;
}
public void TestFunc()
{
var command = cnn.CreateCommand();
try
{
command.CommandText = "PRODUCTION.UPDATEPRODUCT";
command.CommandType = System.Data.CommandType.StoredProcedure;
DmParameter parm1 = new DmParameter(":V_ID", DmDbType.Int32);
command.Parameters.Add(parm1);
parm1.Value = 1;
parm1.Direction = System.Data.ParameterDirection.Input;
DmParameter parm2 = new DmParameter(":V_NAME", DmDbType.VarChar);
command.Parameters.Add(parm2);
parm2.Value = "红楼梦(下)";
parm2.Direction = System.Data.ParameterDirection.Input;
command.ExecuteNonQuery();
string a, b, c;
command.Parameters.Clear();
command.CommandText = "SELECT NAME, AUTHOR, PUBLISHER FROM PRODUCTION.PRODUCT;";
var reader = command.ExecuteReader();
while (reader.Read())
{
a = reader.GetString(0);
b = reader.GetString(1);
c = reader.GetString(2);
Console.WriteLine("NAME:" + a);
Console.WriteLine("AUTHOR:" + b);
Console.WriteLine("PUBLISHER:" + c);
Console.WriteLine("-------------------");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
ret = 0;
}
}
}
}
以上代码调用存储过程“UPDATEPRODUCT”将 PRODUCT 表中的 PRODUCTID 字段内容为 1 的记录的 NAME 字段内容由"红楼梦"更新为"红楼梦(下)"。
5.8 基本示例
下面的示例使用 DM .NET Data Provider,实现 DM 数据库的连接与查询,代码使用 C#编写:
首先在项目中引用 DmProvider.dll,DmProvider.dll 在达梦数据库安装目录下的 bin 文件夹下可以找到。
using System;
using System.Collections.Generic;
using System.Text;
using Dm;
namespace DMDemo
{
class Demo
{
//返回结果
static int ret = 1;
static DmConnection cnn = new DmConnection();
[STAThread]
static int Main(string[] args)
{
try
{
cnn.ConnectionString = "Server=localhost; User Id=SYSDBA; PWD=sysDBA*00";
cnn.Open();
Demo demo = new Demo();
demo.TestFunc();
cnn.Close();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadLine();
return ret;
}
public void TestFunc()
{
DmCommand command = new DmCommand();
command.Connection = cnn;
try
{
string a, b, c;
command.CommandText = "SELECT NAME, AUTHOR, PUBLISHER FROM PRODUCTION.PRODUCT;";
DmDataReader reader =(DmDataReader)command.ExecuteReader();
while(reader.Read())
{
a = reader.GetString(0);
b = reader.GetString(1);
c = reader.GetString(2);
Console.WriteLine("NAME:" + a);
Console.WriteLine("AUTHOR:" + b);
Console.WriteLine("PUBLISHER:" + c);
Console.WriteLine("-------------------");
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
ret = 0;
}
}
}
}