实战COM(06)----在COM中使用Ole DB连接数据库

类别:VC语言 点击:0 评论:0 推荐:

本文欢迎转载,唯请注明出处及作者 [email protected]
---------------------------------------------------

                   实战COM(06)----在COM中使用Ole DB连接数据库


一、建立组件
1)创建一个进程内组件Step04,在创建的窗口“ATL COM AppWizard - Step 1 of 1”中
选中“Allow merging of proxy/stub code”,加入一个“Simple Object”,取名为“Simple04”
2)在该组件中加入以下方法:
  HRESULT ConnectToSQL(void);
  HRESULT MoveNext(void);
  HRESULT GetAu_id([out, retval]BSTR * bAu_id);
  HRESULT GetAu_lname([out, retval]BSTR * bAu_lname);
  HRESULT GetAu_fname([out, retval]BSTR * bAu_fname);
  HRESULT DisConnect(void);
3)如果你对以上两个步骤还不熟悉,请参考“实战COM(02)----创建一个进程内组件”一文
4)修改代码如下:

文件:Simple04.h
// Simple04.h : Declaration of the CSimple04
#include <atldbcli.h> // 数据库操作

#ifndef __SIMPLE04_H_
#define __SIMPLE04_H_

#include "resource.h"       // main symbols

// 定义一个新类
class CAuthors
{
public:
 // 数据--宽度来源于表Authors
 CHAR m_szAu_Id[11];  
 CHAR m_szAu_lName[40];
 CHAR m_szAu_fName[20];
 
 // 输出绑定
 BEGIN_COLUMN_MAP(CAuthors)
  COLUMN_ENTRY(1, m_szAu_Id)
  COLUMN_ENTRY(2, m_szAu_lName)
  COLUMN_ENTRY(3, m_szAu_fName)
 END_COLUMN_MAP()

 // 参数绑定
 BEGIN_PARAM_MAP(CAuthors)
  COLUMN_ENTRY(1, m_szAu_lName)
 END_PARAM_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CSimple04
class ATL_NO_VTABLE CSimple04 :
 public CComObjectRootEx<CComSingleThreadModel>,
 public CComCoClass<CSimple04, &CLSID_Simple04>,
 public IDispatchImpl<ISimple04, &IID_ISimple04, &LIBID_STEP04Lib>
{
public:
 CSimple04()
 {
  m_hr = E_FAIL;  // 初始化
 }

DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLE04)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CSimple04)
 COM_INTERFACE_ENTRY(ISimple04)
 COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// 加入变量
public:
 CDataSource m_Connection;
 CSession m_session;
 CCommand<CAccessor<CAuthors> > m_Authors;
 HRESULT  m_hr;

// ISimple04
public:
 STDMETHOD(DisConnect)(void);
 STDMETHOD(MoveNext)(void);
 STDMETHOD(GetAu_fname)(/*[out, retval]*/BSTR * bAu_fname);
 STDMETHOD(GetAu_lname)(/*[out, retval]*/BSTR * bAu_lname);
 STDMETHOD(GetAu_id)(/*[out, retval]*/BSTR * bAu_id);
 STDMETHOD(ConnectToSQL)(void);
};

#endif ://__SIMPLE04_H_


// 文件:Simple04.cpp
// Simple04.cpp : Implementation of CSimple04
#include "stdafx.h"
#include "Step04.h"
#include "Simple04.h"
// 加入comutil支持
#include <comutil.h>
#pragma comment( lib, "comsupp.lib" )

/////////////////////////////////////////////////////////////////////////////
// CSimple04

// 连接到服务SQL器,并取回Authors数据
STDMETHODIMP CSimple04::ConnectToSQL()
{ // 如果已经建立了连接,先关闭
 if(SUCCEEDED(m_hr))
 {
  m_session.Close();
  m_Connection.Close();
  // 关闭连接
  m_hr = E_FAIL;
 }

 // 打开数据库
 CDBPropSet dbinit(DBPROPSET_DBINIT);
 dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("GP2000"));  // 服务器名
 dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("sa"));   // 用户名
 dbinit.AddProperty(DBPROP_AUTH_PASSWORD, OLESTR("123"));  // 密码
 dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false);
 dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));  // 数据库名
 dbinit.AddProperty(DBPROP_INIT_LCID, (long)2052);
 dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4);
 m_hr = m_Connection.Open(_T("SQLOLEDB.1"), &dbinit);
 if (FAILED(m_hr)) return m_hr;
 
 m_hr = m_session.Open(m_Connection);
 if (FAILED(m_hr)) 
 {
  m_Connection.Close();
  return m_hr;
 }
 // 设置查询条件  
 strcpy(m_Authors.m_szAu_lName, "%h%");  // au_lname中包含"h"的作者
 m_Authors.Open(m_session,
            "select au_id, au_lname, au_fname from authors where au_lname like ?");

 return S_OK;
}
// 取结果集
STDMETHODIMP CSimple04::MoveNext()
{
 if(SUCCEEDED(m_hr))
 {
  m_hr=m_Authors.MoveNext();
 }
 else
 { // 关闭连接
  DisConnect();
 }

 return m_hr;
}
// 取数据
STDMETHODIMP CSimple04::GetAu_id(BSTR *bAu_id)
{
 if(SUCCEEDED(m_hr))
 {
  *bAu_id = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_Id);
 }

 return S_OK;
}

STDMETHODIMP CSimple04::GetAu_lname(BSTR *bAu_lname)
{
 if(SUCCEEDED(m_hr))
 {
  *bAu_lname = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_lName);
 }

 return S_OK;
}

STDMETHODIMP CSimple04::GetAu_fname(BSTR *bAu_fname)
{
 if(SUCCEEDED(m_hr))
 {
  *bAu_fname = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_fName);
 }

 return S_OK;
}

STDMETHODIMP CSimple04::DisConnect()
{
 if(SUCCEEDED(m_hr))
 {
  m_session.Close();
  m_Connection.Close();
  // 关闭连接
  m_hr = E_FAIL;
 }

 return S_OK;
}

二、建立客户端
1)文件如下:
// Client.cpp 文件

#include <windows.h>
#include <stdio.h>
#include <winerror.h>
// 加入comutil支持
#include <comutil.h>
#pragma comment( lib, "comsupp.lib" )

// 包含com的定义文件,以下两个文件从step04中拷贝出来
#include "..\step04\step04.h"
#include "..\step04\step04_i.c"

void main()
{
 ISimple04 * pISimple04=NULL;  // 我们定义的接口
 BSTR  bAu_id, bAu_lname, bAu_fname; // 定义数据
 char *pAu_id, *pAu_lname, *pAu_fname;

 // 初始化
 HRESULT hr = CoInitialize(NULL);
 if(FAILED(hr))
 {
  printf("Coinitialize failed! hr=0x%x", hr);
  return ;
 }

 // 创建COM对象
 hr = CoCreateInstance(CLSID_Simple04, NULL, CLSCTX_ALL,
                    IID_ISimple04, (void **)&pISimple04);
 if(FAILED(hr))
 {
  printf("create com failed! hr=0x%x", hr);
  CoUninitialize();
  return ;
 }
 // 连接SQL
 hr = pISimple04->ConnectToSQL();
 if(FAILED(hr))
 {
  printf("pISimple04->ConnectToSQL() failed! hr=0x%x", hr);
  pISimple04->Release();
  CoUninitialize();
  return ;
 }
 // 取数据
 printf("au_id\tau_lname\t\t\tau_fname\n");
 while (pISimple04->MoveNext() == S_OK)
 {
  pISimple04->GetAu_id(&bAu_id);
  pISimple04->GetAu_lname(&bAu_lname);
  pISimple04->GetAu_fname(&bAu_fname);

  pAu_id = _com_util::ConvertBSTRToString(bAu_id);
  pAu_lname = _com_util::ConvertBSTRToString(bAu_lname);
  pAu_fname = _com_util::ConvertBSTRToString(bAu_fname);

  printf("%s\t%s\t\t\t%s\n", pAu_id, pAu_lname, pAu_fname);

  // 释放分配的内存
  SysFreeString(bAu_id);
  SysFreeString(bAu_lname);
  SysFreeString(bAu_fname);
  delete pAu_id;
  delete pAu_lname;
  delete pAu_fname;
 }
 // 断开连接
 pISimple04->DisConnect();
 pISimple04->Release();
 CoUninitialize();

 return ;
}

三、说明
1)你必须有访问SQL Server数据库pubs中的表authors的权限
2)我使用了一些诸如CDataSource的类来访问SQL SERVER,你也可以直接使用SQL Provider提供的接口来
访问数据库,不过使用SQL Provider提供的接口会更复杂一些。
3)本文简单演示了一个SELECT的语句,可以将该SELECT换成一个存储过程,用Execute执行
4)本文没有涉及到事务的处理,我将在下一篇说明如何在COM+中使用事务
5)也可以将本文创建的组件配置成COM+的应用,可参考“实战COM(05)----创建一个COM+应用”

本文地址:http://com.8s8s.com/it/it3253.htm