Interface
|
Description
|
IDBInitialize
|
Used to initialize and uninitialize data source objects and enumerators. An enumerator is an object used to enumerate the data sources available as well as other enumerators. A consumer should rely on enumerators instead of snooping in the registry when it comes to looking for data sources.
|
IDBProperties
|
Used to set and get the properties on the data source object and to get information about all the properties of the provider.
|
IDBCreateSession
|
Used to create a new session.
|
IPersist
|
Supplies the CLSID of a COM object that can be stored persistently in the system.
|
IGetDataSource
|
Used to provide a Session object with the pointer to its DataSource object.
|
IOpenRowset
|
Used by the session to generate a rowset, a collection of all the rows in the data store. (If commands were supported, a rowset would be the collection of all the rows that satisfy the query.)
|
ISessionProperties
|
Used to get information about the properties a session supports and their settings.
|
IAccessor
|
Manages accessors, the data structures the consumer will use to buffer each row coming from the data store.
|
IConvertType
|
Used to know about the possibility of converting a type into another one within rowsets.
|
IColumnsInfo
|
Exposes information about the columns of a rowset.
|
IRowset
|
Used to fetch rows and fill in the accessors.
|
IRowsetIdentity
|
Used to allow consumers to compare two rows for identity.
|
IRowsetInfo
|
Provides information about a rowset.
|
IRowsetChange
|
Used to update/insert/delete the single fields of a rowset. This interface is strictly required only if you want to support updateability.
|
Figure 5
Current OLE DB Providers
OLE DB Providers
|
Description
|
MSDASQL
|
OLE DB provider used to access data through ODBC. It’s the default provider for ADO 2.x.
|
Microsoft.Jet.OLEDB.3.51, or Microsoft.Jet.OLEDB.4.0
|
Lets consumers treat Microsoft Access archives based either on Jet 3.51 or Jet 4.0.
|
MS Remote
|
The OLE DB Remoting Provider enables consumers to get data from remote OLE DB data providers. A remote provider may run in a different process as well as on a different machine. It can make use of either HTTP or DCOM to communicate.
|
MSDataShape
|
The Data Shaping Service for OLE DB allows applications to create hierarchical relation-ships between keys, fields, and rowsets. The provider supports the Shape language.
|
SQLOLEDB
|
It’s the OLE DB provider that retrieves data from SQL Server 7.0.
|
SQL65Prv
|
Retrieves data from SQL Server 6.5. Know-ledge Base article Q181890 illustrates some problems you can run into along the way.
|
MSDAORA
|
The OLE DB Provider for Oracle makes available whatever Oracle can expose through the Oracle Call Interface API.
|
MSIDXS
|
The OLE DB Provider for Microsoft Index Server provides read-only access to nondatabase, file system, and Web data indexed by Index Server 2.0.
|
SNA Server
|
The SNA Server OLE DB provider is an OLE DB provider for IBM’s Distributed Data Management (DDM) architecture. It provides access to many different mainframe file types including AS/400, VSAM, and DB2.
|
ADSDSOObject
|
It’s the OLE DB provider through which you can access Windows NT, Novell or LDAP directory services via Active Directory Service Interface (ADSI).
|
OLEDB for OLAP
|
OLE DB for OLAP lets you access OLAP data through the standard OLE DB interface. OLAP data are multidimensional data subject to complex relations on which to perform sophisticated data analysis.
|
MSPersist
|
The Microsoft OLE DB Persistence provider lets you save a recordset object into a file and later restore that Recordset object from the file. Schema information, data, and pending changes are also stored.
|
Figure 6
Creating an Email Recordset
'--------------------------------------------------------
' Creates the recordset
'--------------------------------------------------------
Private Function CreateRecordset(ByVal oMsgs As Outlook.Items) As \
ADODB.Recordset
Dim rs As ADODB.Recordset
Dim msg As Outlook.MailItem
Dim i As Integer
' Creates a recordset schema with 3 fields:
' "Sender, Subject, Received"
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient
rs.CursorType = adOpenStatic
rs.LockType = adLockOptimistic
rs.Fields.Append "Sender", adBSTR
rs.Fields.Append "Subject", adBSTR
rs.Fields.Append "Received", adBSTR
rs.Open
' Scan the message collection
i = 1
Set msg = oMsgs.GetFirst
For Each msg In oMsgs
rs.AddNew
rs.Fields("Sender") = msg.SenderName
rs.Fields("Subject") = msg.Subject
rs.Fields("Received") = msg.ReceivedTime
Next
Set CreateRecordset = rs
End Function
Figure 7
A Word Document Recordset
Option Explicit
Private g_rsWordDoc As ADODB.Recordset
Private g_objWordApp As Word.Application
Private Sub Class_GetDataMember(DataMember As String, Data As Object)
Dim doc As Word.Document
Dim par As Word.Paragraph
' Prepare the recordset using DataMember as the file name
Set doc = g_objWordApp.Documents.Open(DataMember, True)
For Each par In doc.Paragraphs
Dim text As String
text = par.Range.text
g_rsWordDoc.AddNew
g_rsWordDoc.Fields("Paragraph").Value = Left(text, Len(text) - 1)
Next
doc.Close
g_rsWordDoc.MoveFirst
Set Data = g_rsWordDoc
End Sub
Private Sub Class_Initialize()
' Initializes the data member
Set g_rsWordDoc = New ADODB.Recordset
g_rsWordDoc.Fields.Append "Paragraph", adBSTR
g_rsWordDoc.Open
' Add the a new data member
DataMembers.Add "Paragraphs"
' Initializes Word
Set g_objWordApp = New Word.Application
End Sub
Private Sub Class_Terminate()
g_rsWordDoc.Close
Set g_rsWordDoc = Nothing
Set g_objWordApp = Nothing
End Sub
Figure 10
ATL COM Wizard-created Classes
Class Name
|
Project File
|
Description
|
CXxxSource
|
XxxDS.h
|
The OLE DB DataSource object. It defines all the properties supported by the provider. Properties are grouped into categories. Feel free to remove from the class declaration the properties you don’t want to expose.
|
CXxxSession
|
XxxSess.h
|
The OLE DB Session object meant to represent a dialog between
|
|
|
providers and consumers. Any data source can support multiple sessions at the same time. Instances of this class are created by CXxxSource. This object handles session properties, creates commands, and governs the preparation of the rowset to return.
|
CXxxSessionColSchema
|
XxxSess.h
|
A schema rowset class meant to return metadata information about the columns of the rowset.
|
CXxxSessionPTSchema
|
XxxSess.h
|
A schema rowset class meant to return metadata information about the data types the provider supports.
|
CXxxSessionTRSchema
|
XxxSess.h
|
A schema rowset class meant to return metadata information about the tables exposed by the data source.
|
CXxxCommand
|
XxxRS.h
|
The OLE DB Command object thatlets you specify command strings to pass down to the data source. The association between formal and actual parameters is done through accessors.
|
CXxxRowset
|
XxxRS.h
|
The OLE DB Rowset object that renders a set of rows with data. It allows data retrieval, type conversion, and row comparison.Accessors are used to bind the structure of the columns to a consumer's defined data structure.
|
CXxxWindowsFile
|
XxxRS.h
|
This class represents the row of data. It is the structure where the Rowset accessor will store the data just read from the table. Its members bind to the columns exposed by the data source. The suffix is WindowsFile just because the ATL wizard creates a provider that handles Windows files.
|
Xxx is the name of the project (that is, FileSystem). WindowsFile is a suffix that reflects what the wizard generates but not necessarily what the class will do in your own projects. You might want to rename it.
|
Figure 12
COutlookRowset::Execute
class COutlookRowset : public CRowsetImpl< COutlookRowset, COutlookMessageList,
COutlookCommand>
{
public:
HRESULT Execute(DBPARAMS* pParams, LONG* pcRowsAffected)
{
COutlookMessageList oml;
FILTERMESSAGE fm;
ZeroMemory(&fm, sizeof(FILTERMESSAGE));
// Parse the command text
if (!ParseCommandText(m_strCommandText, &fm))
return DB_E_ERRORSINCOMMAND;
// Read messages using Simple MAPI
LONG cMessages = 1;
MyMapi_GotoFirstMessage();
while(true) {
BOOL bResult;
bResult = MyMapi_GetNextMessage(g_hMAPISession,
oml.szSenderName, oml.szAddress, oml.szSubject,
oml.szReceivedTime);
if (!bResult)
break;
// Check the message against the filter
lstrcpy(fm.pszMsgReceived, oml.szReceivedTime);
lstrcpy(fm.pszMsgSubject, oml.szSubject);
lstrcpy(fm.pszMsgSender, oml.szSenderName);
lstrcpy(fm.pszMsgAddress, oml.szAddress);
if (FilterMessage(&fm))
{
// This line will add the row to the recordset
if (!m_rgRowData.Add(oml))
return E_OUTOFMEMORY;
cMessages ++;
// Did we reach the max number of records?
if (fm.iMaxNumOfRecords >0)
if (cMessages >fm.iMaxNumOfRecords)
break;
}
}
// Stores how many records have been involved
if (pcRowsAffected != NULL)
*pcRowsAffected = cMessages;
return S_OK;
}
};
Figure 13
Outlook Email Provider Syntax
Keyword
|
Usage
|
Description
|
Select
|
Select=string;
|
Filters the messages on the sender’s name. A message is selected if the specified string is part of the sender’s name.
|
By Address
|
By Address
|
If this clause is specified then select works on the email address (not the display name) of the sender. Sometimes, display name and address coincide, but not always. This clause lets you do searching via email and is useful to join with other tables (see later).
|
Case
|
Case=no;
|
If set to no, then the comparisons won’t be case-sensitive.
|
About
|
About=string;
|
Filters the messages on the subject. A message is selected if the specified string is part of the subject line.
|
Max
|
Max=number;
|
Sets the maximum number of messages to retrieve.
|
From
|
From=[datestring] [,datestring]
|
Fixes a time interval for the messages to [,datestring] select. The date has the MAPI format yyyy/mm/dd.
|
Figure 15
Messages.H
// Messages.H : Declaration of the CMessages class
#ifndef __MESSAGES_H_
#define __MESSAGES_H_
class CMessagesAccessor
{
public:
TCHAR m_sender[52];
TCHAR m_address[52];
TCHAR m_subject[52];
TCHAR m_received[32];
BEGIN_COLUMN_MAP(CMessagesAccessor)
COLUMN_ENTRY(1, m_sender)
COLUMN_ENTRY(2, m_address)
COLUMN_ENTRY(3, m_subject)
COLUMN_ENTRY(4, m_received)
END_COLUMN_MAP()
DEFINE_COMMAND(CMessagesAccessor, _T("Messages"))
void ClearRecord()
{
memset(this, 0, sizeof(*this));
}
};
class CMessages : public CCommand<CAccessor<CMessagesAccessor> >
{
public:
HRESULT Open()
{
// You could add here an argument being the command text to execute
// and pass it to OpenRowset().
HRESULT hr;
hr = OpenDataSource();
if (FAILED(hr))
return hr;
return OpenRowset();
}
HRESULT OpenDataSource()
{
HRESULT hr;
CDataSource db;
CDBPropSet dbinit(DBPROPSET_DBINIT);
hr = db.Open(_T("MailProvider.Outlook.1"), &dbinit);
if (FAILED(hr))
return hr;
return m_session.Open(db);
}
HRESULT OpenRowset()
{
// CCommand::Open can accept a 2nd argument being the command text
return CCommand<CAccessor<CMessagesAccessor> >::Open(m_session);
}
CSession m_session;
};
#endif // __MESSAGES_H_