How can I query a MS SQL Compact Server 3.5 database in C++ not using the OLE DB API?

♀尐吖头ヾ 提交于 2019-12-02 01:48:07
Stephen Quan

I just noticed you mentioned no COM. If it weren't for that I would have suggested ADO. Recently I posted some OLEDB code for Raw C++ code to display the names of tables in an SQL compact server using OLE DB that you may find useful.

Otherwise, if you wish want to see my ADODB in C++ answer (that involves COM), I've worked through converting a ADODB VBScript example:

Dim con, rs
Set con = CreateObject("ADODB.Connection")
REM con.Provider = "Microsoft.SQLLITE.MOBILE.OLEDB.3.0"
con.Provider = "Microsoft.SQLSERVER.CE.OLEDB.3.5"
con.Open "InsertYourDatabase.sdf"
Set rs = con.Execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES")
While not rs.EOF
  WScript.Echo rs.Fields.Item(0).Value
  rs.MoveNext
Wend

To use ADODB in C++ is somewhat arduous, but, it is possible. The following C++ console application shows how to do this by using #import on the ADODB library:

#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <oleauto.h>
#include <atlbase.h>
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" raw_interfaces_only, raw_native_types, no_namespace, named_guids

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = S_OK;

    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

    // Open a SQL Server CE 3.5 database.
    CComPtr<_Connection> spConnection;
    hr = spConnection.CoCreateInstance(CLSID_Connection);
    //hr = spConnection->put_Provider(CComBSTR(L"Microsoft.SQLLITE.MOBILE.OLEDB.3.0"));
    hr = spConnection->put_Provider(CComBSTR(L"Microsoft.SQLSERVER.CE.OLEDB.3.5"));
    hr = spConnection->Open(CComBSTR(L"InsertYourDatabase.sdf"), CComBSTR(L""), CComBSTR(L""), -1);

    // Execute a query.
    CComPtr<_Recordset> spRecordset;
    CComVariant varRecordsAffected;
    hr = spConnection->Execute(CComBSTR(L"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES"), &varRecordsAffected, -1, &spRecordset);

    // Fetch the results.
    VARIANT_BOOL bEOF = VARIANT_TRUE;
    hr = spRecordset->get_EOF(&bEOF);
    while (SUCCEEDED(hr) && bEOF != VARIANT_TRUE)
    {
        // Fetch the TABLE_NAME.
        CComPtr<Fields> spFields;
        hr = spRecordset->get_Fields(&spFields);
        CComPtr<Field> spField;
        hr = spFields->get_Item(CComVariant((int) 0), &spField);
        CComVariant varTableName;
        hr = spField->get_Value(&varTableName);

        // Display the record.
        if (varTableName.vt == VT_BSTR)
        {
            wprintf(L"%s\n", V_BSTR(&varTableName));
        }

        // Move to the next record.
        hr = spRecordset->MoveNext();
        bEOF = VARIANT_TRUE;
        hr = spRecordset->get_EOF(&bEOF);
    }

    // Release smart pointers.
    spRecordset = NULL;
    spConnection = NULL;

    CoUninitialize();
    return 0;
}

You can extract the IDL of ADODB by using OleView (on my PC it was installed with Visual Studio under C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\OleView.exe). Once you have OleView running:

  • File > View TypeLib ...
  • Navigate to C:\Program Files\Common Files\System\ADO\msado15.dll
  • Click Open

This will give you a full syntax of the ADODB library which will help you use it in C++. You can also refer to Microsoft MSDN's ADO API Reference.

For those who are interested in how the issue is resolved.

One does not have to install SqlCE in order to use its COM API.

Here are the steps:

  1. Make sure you have the right dlls.

    For SqlCE 3.0 the dlls are:

    • sqlceca30.dll
    • sqlcecompact30.dll
    • sqlceer30xx.dll
    • sqlceme30.dll
    • sqlceoledb30.dll
    • sqlceqp30.dll
    • sqlcese30.dll

    for SqlCE 3.5:

    • sqlceca35.dll
    • sqlcecompact35.dll
    • sqlceer35EN.dll
    • sqlceme35.dll
    • sqlceoledb35.dll
    • sqlceqp35.dll
    • sqlcese35.dll

    and for SqlCE 4.0:

    • sqlceca40.dll
    • sqlcecompact40.dll
    • sqlceer40EN.dll
    • sqlceme40.dll
    • sqlceoledb40.dll
    • sqlceqp40.dll
    • sqlcese40.dll

    You may also need the .h file for the definitions of the respective COM classes. I have these:

    • sqlce_err.h
    • sqlce_oledb.h
    • sqlce_sync.h
  2. Given an sdf Sql CE database file you have to determine which version it belongs to. Google for it, basically you need to read the first 16 bytes of the file, find the magic number and it determines the version.

  3. Knowing the Sql CE version, locate the directory containing the respective Sql CE dlls (see above).
  4. Call ::LoadLibrary win32 API for the sqlceoledbNN.dll, where NN is 30, 35 or 40. It depends on other dlls, so they must be near it.
  5. Call ::GetProcAddress win32 API to get the address of the exported DllGetClassObject function.
  6. Having at hand the pointer to the DllGetClassObject you are ready to exercise the COM API provided by the Sql CE.

"Enjoy"

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!