Podpora sad řádků schématu
Sady řádků schématu umožňují spotřebitelům získat informace o úložišti dat bez znalosti jeho základní struktury nebo schématu.Úložiště dat může mít například tabulky uspořádané do uživatelem definované hierarchie, takže by zde nebyl žádný způsob jak zajistit znalost schématu s výjimkou jeho přečtení.(Jako další příklad si všimněte, že průvodci Visual C++ používají sady řádků schématu pro generování přístupových objektů pro příjemce.) Aby to příjemci umožnili, vystavuje objekt relace poskytovatele metody na rozhraní IDBSchemaRowset.V aplikacích Visual C++ použijete třídu IDBSchemaRowsetImpl pro implementaci IDBSchemaRowset.
IDBSchemaRowsetImpl podporuje následující metody:
CheckRestrictions kontroluje platnost omezení proti sadě řádků schématu.
CreateSchemaRowset implementuje funkci pro vytvoření objektu modelu COM pro objekt, určený parametrem šablony.
SetRestrictions určuje, která omezení podporujete na konkrétní sadě řádků schématu.
IDBSchemaRowset::GetRowset vrací sadu řádků schématu (zděděnou z rozhraní).
GetSchemas vrací seznam sad řádků schématu, přístupných pomocí IDBSchemaRowsetImpl::GetRowset (zděděno z rozhraní).
Podpora průvodce zprostředkovatele OLE DB knihovny ATL
Průvodce zprostředkovatele OLE DB knihovny ATL vytvoří tři třídy schématu v souboru hlaviček relace:
CShortNameSessionTRSchemaRowset
CShortNameSessionColSchemaRowset
CShortNameSessionPTSchemaRowset
Tyto třídy odpovídají na požadavky spotřebitelů na informace schématu; nezapomeňte, že specifikace OLE DB vyžaduje, aby byly podporovány tyto tři sady řádků schématu:
CShortNameSessionTRSchemaRowset zpracovává požadavky na informace o tabulce (sada řádků schématu DBSCHEMA_TABLES).
CShortNameSessionColSchemaRowset zpracovává požadavky na informace o sloupci (sada řádků schématu DBSCHEMA_COLUMNS).Průvodce poskytuje vzorové implementace pro tyto třídy, které vrací informace o schématu pro poskytovatele DOS.
CShortNameSessionPTSchemaRowset zpracovává požadavky na informace schématu o typu poskytovatele (sada řádků schématu DBSCHEMA_PROVIDER_TYPES.Výchozí implementace poskytovaná průvodcem vrací S_OK.
Můžete přizpůsobit tyto třídy pro zpracování informací o schématu na základě vašeho poskytovatele:
V CShortNameSessionTRSchemaRowset musíte vyplnit pole katalog, tabulka a popis (trData.m_szType, trData.m_szTable a trData.m_szDesc).Průvodcem vygenerovaný příklad používá pouze jeden řádek (tabulku).Jiní poskytovatelé mohou vrátit více než jednu tabulku.
V CShortNameSessionColSchemaRowset předáte název tabulky jako DBID.
Nastavení omezení
Důležitou koncepcí v podpoře sad řádků schématu je nastavení omezení, které provedete pomocí SetRestrictions.Omezení umožňují spotřebitelům načítat pouze odpovídající řádky (například vyhledat všechny sloupce v tabulce "MyTable").Omezení jsou volitelná a v případě, kdy není žádné podporováno (výchozí), jsou vždy navrácena všechna data.Pro příklad poskytovatele, který nepodporuje omezení, si prohlédněte ukázku UpdatePV.
Nastavení mapy schématu
Nastavte mapu schématu, jako je tato v Session.h v UpdatePV:
BEGIN_SCHEMA_MAP(CUpdateSession)
SCHEMA_ENTRY(DBSCHEMA_TABLES, CUpdateSessionTRSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_COLUMNS, CUpdateSessionColSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_PROVIDER_TYPES, CUpdateSessionPTSchemaRowset)
END_SCHEMA_MAP()
Pro podporu IDBSchemaRowset musíte podporovat DBSCHEMA_TABLES, DBSCHEMA_COLUMNS a DBSCHEMA_PROVIDER_TYPES.Dle vašeho uvážení můžete přidat další sady řádků schématu.
Deklarujte třídu sady řádků schématu s metodou Execute jako je CUpdateSessionTRSchemaRowset v UpdatePV:
class CUpdateSessionTRSchemaRowset :
public CSchemaRowsetImpl < CUpdateSessionTRSchemaRowset,
CTABLESRow, CUpdateSession >
...
// Execute looks like this; what pointers does the consumer use?
HRESULT Execute(DBROWCOUNT* pcRowsAffected,
ULONG cRestrictions, const VARIANT* rgRestrictions)
Všimněte si, že CUpdateSession dědí z IDBSchemaRowsetImpl, takže má všechny metody zpracování omezení.Pomocí CSchemaRowsetImpl, prohlásit tři podřízené třídy (uvedených ve výše uvedených mapa schématu): CUpdateSessionTRSchemaRowset, CUpdateSessionColSchemaRowset, a CUpdateSessionPTSchemaRowset.Každá z těchto podřízených tříd má metodu Execute, která zpracovává její odpovídající sadu omezení (kritéria vyhledávání).Každá metoda Execute porovnává hodnoty parametrů cRestrictions a rgRestrictions.Prohlédněte si popis těchto parametrů v SetRestrictions.
Pro další informace o tom, která omezení odpovídají konkrétní sadě řádků schématu si prohlédněte tabulku GUID sad řádků schématu v IDBSchemaRowset v OLE DB Programmer's Reference ve Windows SDK.
Například pokud podporujete omezení TABLE_NAME na DBSCHEMA_TABLES, udělali byste následující:
Nejprve vyhledejte DBSCHEMA_TABLES a zjistěte, zda podporuje čtyři omezení (v pořadí).
Omezení sady řádků schématu |
Hodnota omezení |
---|---|
TABLE_CATALOG |
0x1 (binárně 1) |
TABLE_SCHEMA |
0x2 (binárně 10) |
TABLE_NAME |
0x4 (binárně 100) |
TABLE_TYPE |
0x8 (binárně 1000) |
Dále si všimněte, že je jeden bit pro každé omezení.Vzhledem k tomu, že chcete podporovat pouze TABLE_NAME, vrátili byste 0x4 v elementu rgRestrictions.Pokud byste podporovali TABLE_CATALOG a TABLE_NAME, vrátili byste 0x5 (binárně 101).
Ve výchozím nastavení vrací implementace 0 (nepodporuje žádná omezení) pro každou žádost.UpdatePV je příkladem poskytovatele, který podporuje omezení.
Příklad
Tento kód je převzat z ukázky UpdatePV.UpdatePv podporuje tři sady řádků požadované schéma: DBSCHEMA_TABLES, DBSCHEMA_COLUMNS, a DBSCHEMA_PROVIDER_TYPES.Jako příklad jak implementovat podporu schématu ve vašem poskytovateli vás toto téma provede implementací sady řádků DBSCHEMA_TABLE.
[!POZNÁMKA]
Ukázkový kód se může lišit od zde uvedeného; měli byste považovat ukázkový kód jako aktuálnější verzi.
Prvním krokem při přidání podpory schématu je určení, která omezení hodláte podporovat.Pro určení, která omezení jsou k dispozici pro vaši sadu řádků schématu se podívejte do specifikace OLE DB na definici IDBSchemaRowset.Následováním hlavní definice uvidíte tabulku, obsahující název sady řádků schématu, počet omezení a sloupce omezení.Vyberte sadu řádků schématu, kterou chcete podporovat a poznamenejte si počet omezení a sloupců omezení.Například DBSCHEMA_TABLES podporuje čtyři omezení (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME a TABLE_TYPE):
void SetRestrictions(ULONG cRestrictions, GUID* rguidSchema,
ULONG* rgRestrictions)
{
for (ULONG l=0; l<cRestrictions; l++)
{
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
else if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_COLUMNS))
rgRestrictions[l] = 0x04;
else if (InlineIsEqualGUID(rguidSchema[l],
DBSCHEMA_PROVIDER_TYPES))
rgRestrictions[l] = 0x00;
}
}
Bit představuje každý sloupec omezení.Pokud chcete podporovat omezení (to znamená, že se jím můžete dotazovat), nastavte tento bit na 1.Pokud nechcete omezení podporovat, nastavte daný bit na nulu.Z řádku kódu výše UpdatePV podporuje omezení TABLE_NAME a TABLE_TYPE na sadě řádků DBSCHEMA_TABLES.Jedná se o třetí (bitová maska 100) a čtvrté (bitová maska 1000) omezení.Proto je bitová maska pro UpdatePv 1100 (nebo 0x0C):
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
Následující funkce Execute je podobná těm v normálních sadách řádků.Obsahuje tři argumenty: pcRowsAffected, cRestrictions, a rgRestrictions.Proměnná pcRowsAffected je výstupní parametr, pomocí kterého může poskytovatel vrátit počet řádků v sadě řádků schématu.Parametr cRestrictions je vstupní parametr, obsahující počet předaných omezení příjemce k poskytovateli.Parametr rgRestrictions je pole hodnot VARIANT, které obsahuje hodnoty omezení.
HRESULT Execute(DBROWCOUNT* pcRowsAffected, ULONG cRestrictions,
const VARIANT* rgRestrictions)
Proměnná cRestrictions je založena na celkovém počtu omezení pro sadu řádků schématu bez ohledu na to, zda je poskytovatel podporuje.Vzhledem k tomu, že UpdatePv podporuje dvě omezení (třetí a čtvrté), tento kód pouze vyhledá hodnotu cRestrictions větší nebo rovnou třem.
Hodnota pro omezení TABLE_NAME je uložena v rgRestrictions[2] (znovu, třetí omezení v poli číslovaném od nuly je 2).Je třeba zkontrolovat, zda omezení není VT_EMPTY pro jeho skutečnou podporu.Všimněte si, že VT_NULL se nerovná VT_EMPTY.VT_NULL určuje platnou hodnotu omezení.
Definice UpdatePv názvu tabulky je plně kvalifikovaný název cesty k textovému souboru.Extrahujte hodnotu omezení a poté se pokuste soubor otevřít pro zajištění toho, že soubor skutečně existuje.Pokud soubor neexistuje, vrátí S_OK.To se může zdát poněkud obrácené, ale to co kód skutečně sděluje příjemci je, že nebyly podle zadaného názvu žádné podporované tabulky.Návrat S_OK znamená, že se kód spustil správně.
USES_CONVERSION;
enum {
sizeOfszFile = 255
};
CTABLESRow trData;
FILE *pFile = NULL;
TCHAR szFile[ sizeOfszFile ];
errcode err = 0;
// Handle any restrictions sent to us. This only handles
// the TABLE_NAME & TABLE_TYPE restictions (the 3rd and 4th
// restrictions in DBSCHEMA_TABLES...look in IDBSchemaRowsets
// in part 2 of the prog. ref) so your restrictions are 0x08 & 0x04
// for a total of (0x0C)
if (cRestrictions >= 3 && rgRestrictions[2].vt != VT_EMPTY)
{
CComBSTR bstrName = rgRestrictions[2].bstrVal;
if ((rgRestrictions[2].vt == VT_BSTR) && (bstrName != (BSTR)NULL))
{
// Check to see if the file exists
_tcscpy_s(&szFile[0], sizeOfszFile, OLE2T(bstrName));
if (szFile[0] == _T('\0') ||
((err = _tfopen(&pFile, &szFile[0], _T("r"))) == 0))
{
return S_OK;// Their restriction was invalid return no data
}
else
{
fclose(pFile);
}
}
}
Podpora čtvrtého omezení (TABLE_TYPE) je podobná třetímu omezení.Zkontrolujte, že hodnota není VT_EMPTY.Toto omezení pouze vrací typ tabulky TABLE.Pro určení platných hodnot pro DBSCHEMA_TABLES se podívejte do dodatku B OLE DB Programmer's Reference v oddílu TABLES rowset.
// TABLE_TYPE restriction:
if (cRestrictions >=4 && rgRestrictions[3].vt != VT_EMPTY)
{
CComBSTR bstrType = rgRestrictions[3].bstrVal;
if ((rgRestrictions[3].vt == VT_BSTR) && (bstrType != (BSTR)NULL))
{
// This is kind of a blind restriction.
// This only actually supports
// TABLES so if you get anything else,
// just return an empty rowset.
if (_tcscmp(_T("TABLE"), OLE2T(bstrType)) != 0)
return S_OK;
}
}
Zde ve skutečnosti vytvoříte položku řádku pro sadu řádků.Proměnná trData odpovídá CTABLESRow, struktuře definované v šablonách zprostředkovatele OLE DB.CTABLESRow odpovídá definici sady řádků TABLES v dodatku B specifikace OLE DB.Máte pouze jeden řádek pro přidání, protože můžete v jednu chvíli podporovat pouze jednu tabulku.
// Bring over the data:
wcspy_s(trData.m_szType, OLESTR("TABLE"), 5);
wcspy_s(trData.m_szDesc, OLESTR("The Directory Table"), 19);
wcsncpy_s(trData.m_szTable, T2OLE(szFile), _TRUNCATE());
UpdatePV nastaví pouze tři sloupce: TABLE_NAME, TABLE_TYPE, a Popis.Měli byste si poznamenat sloupce, pro které vracíte informace, protože tyto informace potřebujete při implementaci GetDBStatus:
_ATLTRY
{
m_rgRowData.Add(trData);
}
_ATLCATCHALL()
{
return E_OUTOFMEMORY;
}
//if (!m_rgRowData.Add(trData))
// return E_OUTOFMEMORY;
*pcRowsAffected = 1;
return S_OK;
}
Funkce GetDBStatus je velmi důležitá pro správné fungování sady řádků schématu.Protože nevracíte data pro každý sloupec v sadě řádků TABLES, je nutné určit, pro které sloupce vracíte data pro a které ne.
virtual DBSTATUS GetDBStatus(CSimpleRow* , ATLCOLUMNINFO* pColInfo)
{
ATLASSERT(pColInfo != NULL);
switch(pColInfo->iOrdinal)
{
case 3: // TABLE_NAME
case 4: // TABLE_TYPE
case 6: // DESCRIPTION
return DBSTATUS_S_OK;
break;
default:
return DBSTATUS_S_ISNULL;
break;
}
}
Protože vaše funkce Execute vrací data pro položky TABLE_NAME, TABLE_TYPE a DESCRIPTION ze sady řádků TABLES, můžete se podívat do dodatku B specifikace OLE DB a určit (počítáním shora), že jsou řadovými číslovkami 3, 4 a 6.Pro každý z těchto sloupců vrátí DBSTATUS_S_OK.Pro všechny ostatní sloupce vrátí DBSTATUS_S_ISNULL.Je důležité vrátit tento stav, protože příjemce nemusí pochopit, že hodnota, kterou vrátíte, je NULL nebo něco jiného.Znovu si všimněte, že NULL není shodná s prázdnou.
Pro další informace o rozhraní sady řádků schématu OLE DB si prohlédněte rozhraní IDBSchemaRowset v OLE DB Programmer's Reference.
Pro informace o tom, jak mohou příjemci použít metody IDBSchemaRowset si prohlédněte Získávání metadat se sadami řádků schématu.
Pro příklad poskytovatele, který podporuje sady řádků schématu si prohlédněte ukázku UpdatePV.