在C#中通过OCI来访问Oracle数据库,但是在调用OCIServerAttach接口时出现问题。
Oracle官方的OCI文档中,OCIServerAttach接口的声明方式如下:
sword   OCIServerAttach  (OCIServer *srvhp, OCIError *errhp,
                          CONST OraText *dblink, sb4 dblink_len, ub4 mode);在.NET中,为了调用OCI接口,创建以下类:
internal class OciNativeMethods
{
    [DllImport(@"oci.dll", EntryPoint = "OCIEnvCreate", CharSet = CharSet.Unicode)]
    internal static extern int OCIEnvCreate(out IntPtr envp, int mode, IntPtr ctxp, IntPtr malocfp, IntPtr ralocfp, IntPtr mfreefp, int xtramem_sz, IntPtr usrmempp);    [DllImport(@"oci.dll", EntryPoint = "OCIHandleAlloc", CharSet = CharSet.Unicode)]
    internal static extern int OCIHandleAlloc(IntPtr parenth, out IntPtr hndlpp, int type, int xtramem_sz, IntPtr usrmempp);    [DllImport(@"oci.dll", EntryPoint = "OCIHandleFree", CharSet = CharSet.Unicode)]
    internal static extern int OCIHandleFree(IntPtr hndlp, int type);    [DllImport(@"oci.dll", EntryPoint = "OCIServerAttach", CharSet = CharSet.Unicode)]
    internal static extern int OCIServerAttach(IntPtr srvhp, IntPtr errhp, string dblink, int dblink_len, int mode);    [DllImport(@"oci.dll", EntryPoint = "OCIErrorGet", CharSet = CharSet.Unicode)]
    internal static extern int OCIErrorGet(IntPtr hndlp, int recordno, IntPtr sqlstate, out int errcodep, IntPtr bufp, int bufsiz, int type);    ......    internal const int OCI_DEFAULT = 0x00000000;
    internal const int OCI_THREADED = 0x00000001;
    internal const int OCI_OBJECT = 0x00000002;
    internal const int OCI_EVENTS = 0x00000004;
    internal const int OCI_SHARED = 0x00000010;    ......
}internal class OciContext
{
    internal IntPtr EnviromentHandle = IntPtr.Zero;
    internal IntPtr ServerHandle = IntPtr.Zero;
    internal IntPtr ServerConextHandle = IntPtr.Zero;
    internal IntPtr ErrorHandle = IntPtr.Zero;
    internal IntPtr SessionHandle = IntPtr.Zero;
    internal IntPtr StatementHandle = IntPtr.Zero;
}以下为测试代码:
public partial class Form1 : Form
{
......        private void button1_Click(object sender, EventArgs e)
        {
            OciContext context = new OciContext();
            int status = Oci_InitContext(context);
            DebugLog.Write("初始化OCI上下文失败,返回状态: " + status);
            Console.WriteLine("初始化OCI上下文失败,返回状态: " + status);
        }        /// <summary>
        /// 初始化OCI上下文。
        /// </summary>
        /// <param name="context">OCI上下文。</param>
        /// <returns>执行状态。</returns>
        private int Oci_InitContext(OciContext context)
        {
            //创建OCI环境
            int status = OciNativeMethods.OCIEnvCreate(out context.EnviromentHandle, OciNativeMethods.OCI_DEFAULT, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero);
            if (status != OciNativeMethods.OCI_SUCCESS) return status;            //申请错误句柄
            status = OciNativeMethods.OCIHandleAlloc(context.EnviromentHandle, out context.ErrorHandle, OciNativeMethods.OCI_HTYPE_ERROR, 0, IntPtr.Zero);
            if (status != OciNativeMethods.OCI_SUCCESS) return status;            //申请服务器句柄
            status = OciNativeMethods.OCIHandleAlloc(context.EnviromentHandle, out context.ServerHandle, OciNativeMethods.OCI_HTYPE_SERVER, 0, IntPtr.Zero);
            if (status != OciNativeMethods.OCI_SUCCESS) return status;            //申请服务器上下文句柄S
            status = OciNativeMethods.OCIHandleAlloc(context.EnviromentHandle, out context.ServerConextHandle, OciNativeMethods.OCI_HTYPE_SVCCTX, 0, IntPtr.Zero);
            if (status != OciNativeMethods.OCI_SUCCESS) return status;            //连接数据库服务器
            string dblink = "ORCL";
status = OciNativeMethods.OCIServerAttach(context.ServerHandle, context.ErrorHandle, dblink, dblink.Length << 1, OciNativeMethods.OCI_DEFAULT);
            if (status != OciNativeMethods.OCI_SUCCESS)
            {
                Console.WriteLine("连接失败:" + Oci_GetError(context.ErrorHandle));
                return status;
            }

            Console.WriteLine("连接成功。");            ......            return status;
        } ......
}执行到红色部分时出错,返回的状态代码为-1。
需要说明的是,我在本机上装了一个Oracle10g,SID是ORCL,tnsnames.ora文件的完整内容是:
# tnsnames.ora Network Configuration File: c:\oracle\product\10.2.0\db_1\network\admin\tnsnames.ora
# Generated by Oracle configuration tools.ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = ms-c3a782ca83be)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orcl)
    )
  )EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )我用PL/SQL Developer是可以登录的。请大家帮忙看看是怎么回事,急等,谢谢。