C#/C++ 通过ODBC连接OceanBase Oracle租户

odbc,oceanbase,oracle · 浏览次数 : 0

小编点评

```csharp using System; using System.Data.Odbc; namespace ConsoleApp { internal class Program { static void Main(string[] args) { // 使用 DSN 连接数据库 string connectionString = @"DSN=OceanBase ODBC;Uid=用户名@住户名#集群;Pwd=密码;"; using (OdbcConnection connection = new OdbcConnection(connectionString)) { try { connection.Open(); Console.WriteLine("Connected to Oracle database!\n"); // 执行查询 string query = "SELECT * FROM TIERS WHERE ROWNUM <= 1;"; using (OdbcCommand command = new OdbcCommand(query, connection)) { using (OdbcDataReader reader = command.ExecuteReader()) { while (reader.Read()) { int id = reader.GetInt32(0); string name = reader.GetString(1); Console.WriteLine($"ID: {id}, Name: {name}"); } } } connection.Close(); } catch (Exception ex) { Console.WriteLine("Error executing query:", ex.Message); } } // 使用 NHibernate 连接数据库 string baseDirectory = AppDomain.CurrentDomain.BaseDirectory; var cfg = new Configuration().Configure(Path.Combine(baseDirectory, "NHibernate.cfg.xml")); cfg.AddFile(Path.Combine(baseDirectory, "TestEntity.xml")); var sessionFactory = cfg.BuildSessionFactory(); using (var session = sessionFactory.OpenSession()) { var query = session.CreateQuery("FROM TestEntity") .SetMaxResults(10); var results = query.List(); } } } } ``` **其他说明:** * 代码假设你已经安装了 Oracle 数据库驱动。 * `NHibernate.cfg.xml` 中的 `TestEntity.xml` 是你数据库中 `TESTENTITY` 表的映射文件。 * `Program` 类中的代码展示了两种连接数据库的方式,分别使用 DSN 和 NHibernate。

正文

概述

近期我们项目正处于将Oracle数据库迁移到OceanBase Oracle租户模式的阶段。考虑到我们项目采用了C++和C#混合开发,并且使用了多种技术,因此存在多种数据库连接方式。然而,针对C#连接OceanBase的案例相对较少,因此我特意记录下这一过程。

开放数据库互连(ODBC)是微软公司开放服务结构(WOSA,Windows Open Services Architecture)中有关数据库的一个组成部分,基本思想是为用户提供简单、标准、透明的数据库连接的公共编程接口,开发厂商根据 ODBC 的标准去实现底层的驱动程序,这个驱动对用户是透明的,并允许根据不同的 DBMS 采用不同的技术加以优化实现。

驱动下载

下载地址:https://www.oceanbase.com/softwarecenter-cloud

根据平台类型选择驱动。

驱动配置

打开 ODBC 数据源管理员:在 Windows 中,按下 Windows键 + R 打开“运行”对话框,然后输入 odbcad32 并按下 Enter 键,这将打开 ODBC 数据源管理员。

 选择系统的或用户的数据源:在 ODBC 数据源管理员中,有两个选项卡:用户 DSN 和 系统 DSN。选择一个适合你的选项,通常建议选择 系统 DSN,因为它对所有用户都可用。

添加一个新的数据源:点击 添加 按钮,然后在弹出的对话框中选择 OceanBase ODBC 2.0 Driver 数据库。

配置数据源连接信息:在配置 OceanBase 数据库数据源时,你需要提供以下信息:

数据源名称(DSN):为你的数据源指定一个唯一的名称。这里命名为OceanBase ODBC

描述:提供有关此数据源的描述,以便识别它。

 TNS 服务名称:输入你要连接的 Oracle 服务的 TNS 服务名称。IP: XX.XX.XX.XX

用户名和密码:提供用于连接到 Oracle 数据库的用户名和密码。

 UserName: 用户名@租户名#集群

测试连接:在完成配置后,你可以点击 测试连接 按钮来验证是否能够成功连接到 OceanBase Oracle 数据库。

注意:不通过DSN也可以连接

C++ 代码案例

#include <stdio.h>
#include <assert.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <iostream>

void print_error(SQLSMALLINT HandleType, SQLHANDLE Handle) {
    SQLWCHAR SQLState[6];
    SQLINTEGER NativeError;
    SQLWCHAR SQLMessage[SQL_MAX_MESSAGE_LENGTH] = { 0 };
    SQLSMALLINT TextLengthPtr;

    SQLGetDiagRec(HandleType, Handle, 1, SQLState, &NativeError, SQLMessage, SQL_MAX_MESSAGE_LENGTH, &TextLengthPtr);
    std::wcerr << L"[" << SQLState << L"] (" << NativeError << L") " << SQLMessage << std::endl;
}

int main() {
    // Allocate environment handle
    SQLHANDLE henv;
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);

    // Allocate connection handle
    SQLHANDLE hdbc;
    SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

    // Connection string

    //使用DSN
    SQLWCHAR* connectionString = (SQLWCHAR*)L"DSN=OceanBase ODBC;UID=用户名@住户名#集群;PWD=密码";

    //不使用DSN
    //SQLWCHAR* connectionString = (SQLWCHAR*)L"Driver={OceanBase ODBC 2.0 Driver};Server=xx.xx.xx.xx;Port=2883;Database=用户名;User=用户名@住户名#集群;Password=密码;Option=3;";

    // Connect to the database
    SQLRETURN retcode = SQLDriverConnect(hdbc, NULL, connectionString, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error connecting to database:" << std::endl;
        print_error(SQL_HANDLE_DBC, hdbc);
        return 1;
    }

    std::cout << "Connected to database successfully!" << std::endl;

    // Allocate statement handle
    SQLHANDLE hstmt;
    SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);

    // Execute a query
    SQLWCHAR* query = (SQLWCHAR*)L"SELECT * FROM TIERS WHERE ROWNUM <= 1;";
    retcode = SQLExecDirect(hstmt, query, SQL_NTS);
    if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
        std::cerr << "Error executing query:" << std::endl;
        print_error(SQL_HANDLE_STMT, hstmt);
        SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
        SQLDisconnect(hdbc);
        SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
        SQLFreeHandle(SQL_HANDLE_ENV, henv);
        return 1;
    }

    // Fetch and print results
    SQLCHAR name[256];
    SQLLEN nameLen;
    while (SQLFetch(hstmt) == SQL_SUCCESS) {
        SQLGetData(hstmt, 1, SQL_C_CHAR, name, sizeof(name), &nameLen);
        std::cout << "Name: " << name << std::endl;
    }

    // Cleanup
    SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    SQLDisconnect(hdbc);
    SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    SQLFreeHandle(SQL_HANDLE_ENV, henv);

    return 0;
}

C# 代码案例

using System;
using System.Data.Odbc;

namespace ConsoleApp
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //使用DSN
            string connectionString = "DSN=OceanBase ODBC;Uid=用户名@住户名#集群;Pwd=你的密码;";


            //不使用DSN
            //string connectionString = "Driver={OceanBase ODBC 2.0 Driver};Server=xx.xx.xx.xx;Port=2883;Database=用户名;User=用户名@住户名#集群;;Password=密码;Option=3;";
            using (OdbcConnection connection = new OdbcConnection(connectionString))
            {
                try
                {
                    connection.Open();
                    Console.WriteLine("Connected to Oracle database!");

                    // Perform database operations here

                    string query = "SELECT *FROM TIERS WHERE ROWNUM <= 1;";
                    using (OdbcCommand command = new OdbcCommand(query, connection))
                    {
                        using (OdbcDataReader reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                int id = reader.GetInt32(0); // 假设第一列是 ID
                                string name = reader.GetString(1); // 假设第二列是 Name
                                Console.WriteLine($"ID: {id}, Name: {name}");
                            }
                        }
                    }

                    connection.Close();
                }

        }
    }
}

 

NHibernate示例

安装NHibernate

使用NuGet包管理器安装NHibernate。你可以在Visual Studio中打开NuGet包管理器控制台,然后运行以下命令:

Install-Package NHibernate

这将自动下载并安装NHibernate及其所有依赖项到你的项目中。

配置NHibernate

 

NHibernate.cfg.xml
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
        <property name="connection.driver_class">NHibernate.Driver.OdbcDriver</property>
        <!--<property name="connection.connection_string">DSN=OceanBase ODBC;Database=用户名;Uid=用户名@住户名#集群;Pwd=密码;</property>-->
        <property name="connection.connection_string">Driver={OceanBase ODBC 2.0 Driver};Server=xx.xx.xx.xx;Port=2883;Database=用户名;Uid=用户名@住户名#集群;Pwd=密码;</property>
        <property name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
    </session-factory>
</hibernate-configuration>

配置映射类

public class TestEntity
{
    public virtual int Ident { get; set; }

    public virtual string Name { get; set; }
}

 

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="ConsoleApp2.TestEntity, ConsoleApp2" table="TESTENTITY">
        <id name="Ident" column="IDENT" />
        <property name="Name" column="NAME" />
        <!-- 其他属性映射... -->
    </class>
</hibernate-mapping>

查询案例

using NHibernate.Cfg;
using System;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
        var cfg = new Configuration().Configure(Path.Combine(baseDirectory, "NHibernate.cfg.xml"));
        cfg.AddFile(Path.Combine(baseDirectory, "TestEntity.xml"));

        var sessionFactory = cfg.BuildSessionFactory();
        using (var session = sessionFactory.OpenSession())
        {
            var query = session.CreateQuery("FROM TestEntity")
                .SetMaxResults(10);

            var results = query.List();
        }
    }
}

 

与C#/C++ 通过ODBC连接OceanBase Oracle租户相似的内容:

C#/C++ 通过ODBC连接OceanBase Oracle租户

概述 近期我们项目正处于将Oracle数据库迁移到OceanBase Oracle租户模式的阶段。考虑到我们项目采用了C++和C#混合开发,并且使用了多种技术,因此存在多种数据库连接方式。然而,针对C#连接OceanBase的案例相对较少,因此我特意记录下这一过程。 开放数据库互连(ODBC)是微软

7.4 C/C++ 实现链表栈

相对于顺序栈,链表栈的内存使用更加灵活,因为链表栈的内存空间是通过动态分配获得的,它不需要在创建时确定其大小,而是根据需要逐个分配节点。当需要压入一个新的元素时,只需要分配一个新的节点,并将其插入到链表的头部;当需要弹出栈顶元素时,只需要删除链表头部的节点,并释放其所占用的内存空间即可。由于链表栈的空间利用率更高,因此在实际应用中,链表栈通常比顺序栈更受欢迎。在实现上,链表栈通过使用`malloc

C/C++如何写调试宏

1. 调试宏以及测试 在写代码时,不可避免需要打印提示、警告、错误等信息,且要灵活控制打印信息的级别。另外,还有可能需要使用宏来控制代码段(主要是调试代码段)是否执行。为此,本文提供一种调试宏定义方案,包括打印字符串信息LOG1宏和格式化打印LOG2宏,且能通过宏控制代码段执行。完整代码如下: #i

7.2 C/C++ 实现动态链表

动态链表是一种常用的动态数据结构,可以在运行时动态地申请内存空间来存储数据,相比于静态数组和静态链表,更加灵活和高效。在动态链表中,数据元素被组织成一条链表,每个元素包含了指向下一个元素的指针,这样就可以通过指针将所有元素串联起来。使用动态链表存储数据时,不需要预先申请内存空间,而是在需要的时候才向内存申请。当需要添加新的元素时,可以使用`malloc`函数动态地申请内存空间,然后将新的元素插入到

极速进化,光速转录,C++版本人工智能实时语音转文字(字幕/语音识别)Whisper.cpp实践

业界良心OpenAI开源的Whisper模型是开源语音转文字领域的执牛耳者,白璧微瑕之处在于无法通过苹果M芯片优化转录效率,Whisper.cpp 则是 Whisper 模型的 C/C++ 移植版本,它具有无依赖项、内存使用量低等特点,重要的是增加了 Core ML 支持,完美适配苹果M系列芯片。

[转帖]关于TIME_WAIT优化

我们先看一下四次挥手过程 # netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' # netstat -tan | awk '{print $6}' | sort | uniq -c 通过此图先说明几个概念: TI

5.2 基于ROP漏洞挖掘与利用

通常情况下栈溢出可能造成的后果有两种,一类是本地提权另一类则是远程执行任意命令,通常C/C++并没有提供智能化检查用户输入是否合法的功能,同时程序编写人员在编写代码时也很难始终检查栈是否会发生溢出,这就给恶意代码的溢出提供了的条件,利用溢出攻击者可以控制程序的执行流,从而控制程序的执行过程并实施恶意行为,本章内容笔者通过自行编写了一个基于网络的FTP服务器,并特意布置了特定的漏洞,通过本章的学习,

[转帖]CPU的IPC调优:通过优化代码,提高每个时钟的指令数

目录 代码目录结构 compile-sx.sh compile.sh s1.c s2.c s3.c s4.c alu.c nop.c alu8.c 性能测试 s1.c s2.c s3.c s4.c alu.c nop.c alu8.c 参考 IPC,英文全称“Instruction Per Cloc

C# 设置PDF表单不可编辑、或提取PDF表单数据

PDF表单是PDF中的可编辑区域,允许用户填写指定信息。当表单填写完成后,有时候我们可能需要将其设置为不可编辑,以保护表单内容的完整性和可靠性。或者需要从PDF表单中提取数据以便后续处理或分析。 之前文章详细介绍过如何使用免费Spire.PDF库通过C# 创建、填写表单,本文将继续介绍该免费.NET

一文教你如何调用Ascend C算子

本文分享自华为云社区《一文教你如何调用Ascend C算子》,作者: 昇腾CANN。 Ascend C是CANN针对算子开发场景推出的编程语言,原生支持C和C++标准规范,兼具开发效率和运行性能。基于Ascend C编写的算子程序,通过编译器编译和运行时调度,运行在昇腾AI处理器上。使用Ascend