Zápis obecného kódu pro přístup k datům v ASP.NET 2.0 a ADO.NET 2.0
Dr. Shahram Khosravi
Informační řešení
Duben 2005
Platí pro:
Microsoft ADO.NET 2.0
Microsoft ASP.NET 2.0
Microsoft .NET Framework 2.0
Microsoft Visual Web Developer 2005 Express Edition Beta
Programovací jazyk C#
souhrn : Pomocí podrobného přístupu se dozvíte, jak používat různé nástroje a techniky pro přístup k obecným datům ASP.NET 2.0 a ADO.NET 2.0. (18 tištěných stránek)
Stáhněte si přidružený ukázkový kód: GenericDataAccessSample.exe.
Úvod
Většina webových aplikací obsahuje kód pro přístup k datům pro přístup k podkladovému úložišti dat pro provádění základních operací s daty, jako je Vybrat, Aktualizovat, Odstranita Vložit. Tento článek používá podrobný přístup, který ukazuje, jak můžou vývojáři stránek využívat různé nástroje a techniky ASP.NET 2.0 a ADO.NET 2.0 k zápisu obecného kódu pro přístup k datům, který lze použít pro přístup k různým typům úložišť dat. Psaní obecného kódu pro přístup k datům je zvlášť důležité ve webových aplikacích řízených daty, protože data pocházejí z mnoha různých zdrojů, včetně Microsoft SQL Serveru, Oracle, dokumentů XML, plochých souborů a webových služeb, a to jen pro několik názvů.
Tento článek používá jednoduchou webovou aplikaci jako testovací postel pro veškerý zde uvedený kód. Aplikace se skládá ze dvou částí: první část umožňuje správci systému odesílat bulletiny všem odběratelům seznamu adresátů. Druhá část umožňuje uživatelům odebírat nebo odebírat odběr ze seznamu adresátů. První část článku začíná implementací jednoduchého kódu pro přístup k datům (viz obrázek 1) pro přístup k Microsoft SQL Serveru a extrahování seznamu odběratelů. Kód se upraví a v průběhu článku zogeneruje obecněji.
Obrázek 1 Metoda GetSubscribers extrahuje seznam všech odběratelů.
public IEnumerable GetSubscribers()
{
SqlConnection con = new SqlConnection();
con.ConnectionString = @"Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=D:\Application\Data\Database.mdf";
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandText = "Select * From Subscribers";
com.CommandType = CommandType.Text;
DataSet ds = new DataSet();
SqlDataAdapter ad = new SqlDataAdapter();
ad.SelectCommand = com;
con.Open();
ad.Fill(ds);
con.Close();
return ds.Tables[0].DefaultView;
}
Vzhledem k tomu, že kód pro přístup k datům na obrázku 1 obsahuje kód pro vytváření objektů ADO.NET, například sqlConnection, SqlCommanda instance sqlDataAdapter. Kód pro přístup k datům nelze použít k načtení seznamu odběratelů z jiných úložišť dat, jako je databáze Oracle. Vývojáři stránek musí upravit kód pro přístup k datům (pomocí metody GetSubscribers) pokaždé, když potřebují přístup k novému úložišti dat. Dále se dozvíte, jak ADO.NET 2.0 používá vzor zprostředkovatele, který vývojářům pomáhá psát obecný přístupový kód k datům pro přístup k různým typům úložišť dat.
Model zprostředkovatele ve verzi ADO.NET 2.0
Hlavním problémem s GetSubscribers metoda je, že obsahuje kód pro vytvoření ADO.NET objektů. Podle vzoru poskytovatele musí kód pro přístup k datům delegovat odpovědnost za poskytnutí kódu pro vytvoření ADO.NET objektů do jiné třídy. Tato třída se označuje jako "třída zprostředkovatele kódu", protože poskytuje kód pro vytváření ADO.NET objektů. Třída zprostředkovatele kódu zveřejňuje metody, jako je CreateConnection, CreateCommanda CreateDataAdapter, kde každá metoda poskytuje kód pro vytvoření odpovídajícího ADO.NET objektu.
Vzhledem k tomu, že třída zprostředkovatele kódu obsahuje skutečný kód, nelze stejnou třídu použít pro přístup k různým úložištům dat. Proto je nutné upravit a překonfigurovat kód přístupu k datům (metoda GetSubscribers) tak, aby delegoval odpovědnost za poskytnutí kódu do nové třídy zprostředkovatele kódu pokaždé, když se používá pro přístup k novému úložišti dat. Metoda GetSubscribers je stále svázaná s kódem, i když neobsahuje kód.
Model poskytovatele nabízí řešení tohoto problému a skládá se z následujících kroků:
Návrh a implementace abstraktní základní třídy zprostředkovatele
Odvodit všechny třídy zprostředkovatele kódu z abstraktní základní třídy zprostředkovatele.
Mít přístupový kód dat (Metoda GetSubscribers) použít abstraktní základní třídu místo jednotlivých tříd zprostředkovatele kódu.
Abstraktní základní třída deleguje odpovědnost za poskytnutí kódu pro vytvoření ADO.NET objektů na příslušnou podtřídu. Abstraktní základní třída má název DbProviderFactory. Níže jsou uvedeny některé metody této třídy:
public abstract class DbProviderFactory { public virtual DbConnection CreateConnection(); public virtual DbCommand CreateCommand(); public virtual DbDataAdapter CreateDataAdapter(); }
Každá podtřída poskytuje kód pro vytvoření příslušných ADO.NET objektů pro konkrétní úložiště dat. Například podtřída SqlClientFactory poskytuje kód pro vytvoření objektů ADO.NET pro přístup k Microsoft SQL Serveru, jak je znázorněno na obrázku 2.
Obrázek 2 Třída SqlClientFactory a některé z jejích metod
public class SqlClientFactory : DbProviderFactory { public override DbConnection CreateConnection() { return new SqlConnection(); } public override DbCommand CreateCommand() { return new SqlCommand(); } public override DbDataAdapter CreateDataAdapter() { return new SqlDataAdapter(); } }
Model zprostředkovatele umožňuje kódu přístupu k datům zacházet se všemi podtřídami stejně, protože jsou to všechny podtřídy stejné základní třídy. Pokud jde o kód pro přístup k datům, všechny podtřídy jsou typu DbProviderFactory. Kód pro přístup k datům nemá žádný způsob, jak zjistit konkrétní typ používané podtřídy. To představuje nový problém. Pokud přístupový kód dat (metoda GetSubscribers) nezná typ podtřídy, jak může vytvořit instanci podtřídy?
Řešení tohoto problému se skládá z následujících tří částí:
- Jedinečný řetězec slouží k identifikaci každé podtřídy. ADO.NET 2.0 používá obor názvů podtřídy jako jedinečné ID řetězce. Například jedinečné ID řetězce System.Data.SqlClient a System.Data.OracleClient identifikovat SqlClientFactory a OracleClientFactory podtřídy.
- Textový soubor (obvykle soubor XML) slouží k ukládání informací o všech podtřídách. ADO.NET 2.0 k uložení požadovaných informací používá soubory machine.config a web.config. Informace o podtřídě obsahují mimo jiné jedinečné ID řetězce a název typu podtřídy. Například informace o podtřídě SqlClientFactory zahrnují jedinečné ID řetězce System.Data.SqlClient a název typu podtřídy, tj. System.Data.SqlClient.SqlClientFactory.
- Statická metoda je navržena a implementována. Metoda může být součástí abstraktní základní třídy nebo části samostatné třídy. ADO.NET 2.0 používá samostatnou třídu s názvem DbProviderFactories, která zveřejňuje GetFactory statickou metodu. Metoda přebírá jedinečné ID řetězce požadované podtřídy jako jediný argument a hledá v souboru machine.config podtřídu s daným jedinečným ID řetězce. Metoda extrahuje název typu požadované podtřídy a používá reflexi k dynamickému vytvoření instance podtřídy.
Kód přístupu k datům (metoda GetSubscribers) volá statickou metodu GetFactory a předá příslušné jedinečné ID řetězce pro přístup k instanci odpovídající podtřídy. Jakmile Metoda GetSubscribers přistupuje k instanci, volá příslušné metody vytváření, jako je CreateConnection(), CreateCommand() atd., k vytvoření instance příslušných ADO.NET objektů, jak je znázorněno na obrázku 3.
Obrázek 3 Verze metody GetSubscribers, která používá nový vzor zprostředkovatele ADO.NET
public IEnumerable GetSubscribers()
{
DbProviderFactory provider = DbProviderFactories.GetFactory("System.Data.SqlClient");
DbConnection con = provider.CreateConnection();
con.ConnectionString = @"Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=D:\Application\Data\Database.mdf";
DbCommand com = provider.CreateCommand();
com.Connection = con;
com.CommandText = "Select * From Subscribers";
com.CommandType = CommandType.Text;
DataSet ds = new DataSet();
DbDataAdapter ad = provider.CreateDataAdapter();
ad.SelectCommand = com;
con.Open();
ad.Fill(ds);
con.Close();
return ds.Tables[0].DefaultView;
}
Kód přístupu k datům (metoda GetSubscribers) deleguje odpovědnost za poskytnutí kódu pro vytvoření ADO.NET objektů do instance třídy zprostředkovatele kódu, kterou Metoda GetFactory vytvoří a vrátí. Stejný kód pro přístup k datům je proto možné použít pro přístup k různým úložištům dat, jako je Microsoft SQL Server a Oracle.
Kód pro vytvoření správných ADO.NET objektů je specifické pro úložiště dat. Model zprostředkovatele v ADO.NET 2.0 odebere tyto části specifické pro úložiště dat z kódu přístupu k datům (metoda GetSubscribers), aby byl obecnější. Model poskytovatele ale neodebere všechny části specifické pro úložiště dat. Bližší kontrola metody GetSubscribers odhalí následující zbývající části úložiště dat:
- Připojovací řetězec
- Jedinečné ID řetězce identifikující základní třídu zprostředkovatele kódu
- Text příkazu
- Typ příkazu
Pokud s výše uvedenými částmi něco neuděláte, kód pro přístup k datům je stále svázaný s konkrétním typem úložiště dat. Model poskytovatele v ADO.NET 2.0 s tímto problémem nepomůže. ADO.NET 2.0 nám ale poskytuje další nástroje a techniky pro odebrání prvních dvou částí specifických pro úložiště dat, jako je připojovací řetězec a jedinečné ID řetězce z metody GetSubscribers.
Připojovací řetězce
Připojovací řetězce jsou některé z nejcennějších prostředků ve webové aplikaci. Jsou tak důležité, aby se s rozhraním .NET Framework 2.0 zacházeli jako s "prvotřídními občany". Soubor web.config teď podporuje nový oddíl s názvem <connectionStrings>, který obsahuje všechny připojovací řetězce použité v aplikaci. Proto do této části přesuneme připojovací řetězec z metody GetSubscribers:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add
name="MySqlConnectionString"
connectionString="Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=D:\Application\Data\Database.mdf"
providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
<přidat podelement> elementu <connectionStrings> zveřejňuje následující tři důležité atributy:
- Název– popisný název připojovacího řetězce
- connectionString– skutečný připojovací řetězec
- providerName– jedinečné ID řetězce nebo invariantní třída zprostředkovatele kódu
NET Framework 2.0 poskytuje kód pro přístup k datům (metoda GetSubscribers) se správnými nástroji, které obecně extrahují hodnotu připojovacího řetězce ze souboru web.config, jak je popsáno v následujícím článku. Obor názvů System.Configuration v rozhraní .NET Framework 2.0 obsahuje novou třídu s názvem Configuration. Tato třída představuje celý obsah souboru web.config nebo machine.config. Kód pro přístup k datům nemůže použít nový operátor k přímému vytvoření instance této třídy.
Samotná třída zveřejňuje statickou metodu s názvem GetWebConfiguration, která přebírá cestu k souboru web.config a vrací instanci třídy Configuration, která představuje celý obsah souboru web.config:
Configuration configuration = Configuration.GetWebConfiguration("~/");
Třída, která dědí z třídy ConfigurationSection představuje všechny části souboru web.config. Název třídy se skládá z názvu oddílu a klíčového slova Section. Například ConnectionStringsSection třída představuje obsah <connectionStrings> oddíl souboru web.config. Kód přístupu k datům (metoda GetSubscribers) nemůže použít nový operátor k přímému vytvoření instance ConnectionStringsSection třídy. Třída Configuration zveřejňuje vlastnost kolekce s názvem Sections, která obsahuje všechny objekty, které představují různé části souboru web.config:
ConnectionStringsSection section = (ConnectionStringsSection)configuration.Sections["connectionStrings"];
Vzhledem k tomu, oddíly je kolekce ConfigurationSection objekty, datový přístupový kód musí typ přetypovat vrácenou instanci. Jakmile Metoda GetSubscribers přistupuje k ConnectionStringsSection objektu a použije ho pro přístup k hodnotě připojovacího řetězce:
string connectionString = section.ConnectionStrings["MySqlConnectionString"].ConnectionString;
Obrázek 4 ukazuje novou verzi metody GetSubscribers, která obsahuje požadovaný kód pro extrakci připojovacího řetězce obecným způsobem.
Obrázek 4 Verze metody GetSubscribers, která extrahuje připojovací řetězec ze souboru web.config
public IEnumerable GetSubscribers()
{
DbProviderFactory provider = DbProviderFactories.GetFactory("System.Data.SqlClient");
DbConnection con = provider.CreateConnection();
Configuration configuration = Configuration.GetWebConfiguration("~/");
ConnectionStringsSection section = (ConnectionStringsSection)configuration.Sections["connectionStrings"];
con.ConnectionString = section.ConnectionStrings["MySqlConnectionString"].ConnectionString;
DbCommand com = provider.CreateCommand();
com.Connection = con;
com.CommandText = "Select * From Subscribers";
com.CommandType = CommandType.Text;
DataSet ds = new DataSet();
DbDataAdapter ad = provider.CreateDataAdapter();
ad.SelectCommand = com;
con.Open();
ad.Fill(ds);
con.Close();
return ds.Tables[0].DefaultView;
}
Metoda GetSubscribers nyní obsahuje MySqlConnectionString řetězec, takže stále musíme upravit GetSubscribers metoda přidat podporu pro jiné úložiště dat, jako je databáze Oracle. Zdá se, že jsme zpátky na druhou. Opravdu ne. Získali jsme několik důležitých výhod přesunutím připojovacího řetězce z kódu pro přístup k datům do souboru web.config:
Připojovací řetězec je nyní hodnotou atributu connectionString <přidat> dílčí prvek connectionStrings elementu web.config souboru, což je dokument XML. Skvělou věcí v dokumentu XML je, že můžeme zašifrovat jeden prvek v dokumentu. Nemusíme šifrovat celý dokument, pokud potřebujeme chránit jenom malou část dokumentu. Rozhraní .NET Framework 2.0 obsahuje nástroj, který nám umožňuje zašifrovat <connectionStrings> oddíl k ochraně nejdůležitějšího prostředku, připojovacích řetězců. Představte si, kolik poškození může hacker udělat pro naši cennou databázi, pokud dostane ruku na naše připojovací řetězce. Nezapomeňte, že připojovací řetězce jsou všechny hackery potřeba pro přístup k naší databázi.
Může se zdát, že vše, co jsme udělali, je nahradit následující řetězec.
"Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=D:\Application\Data\Database.mdf"
s novým řetězcem MySqlConnectionString. Existuje však jeden velký rozdíl. První řetězec obsahuje informace specifické pro databázi SQL Serveru, které se nevztahují na jinou databázi, jako je Oracle, ale druhý řetězec je jen popisný název.
Popisný název ale může způsobit problémy, protože odkazuje na konkrétní připojovací řetězec v <connectionStrings> části souboru web.config. V našem příkladu odkazuje na připojovací řetězec použitý pro přístup k Microsoft SQL Serveru. To znamená, že metoda GetSubscribers (kód pro přístup k datům) musí být upravena tak, aby používala jiný popisný název pro přístup k jinému úložišti dat, jako je Oracle.
Abychom se vyhnuli úpravám kódu pro přístup k datům, můžeme popisný název přesunout z kódu pro přístup k datům do části <appSettings> souboru web.config a dynamicky extrahovat kód pro přístup k datům za běhu následujícím způsobem:
string connectionStringName = ConfigurationSettings.AppSettings["ConnectionStringName"];
Název zprostředkovatele také přesuneme do oddílu <appSettings>:
string providerName = ConfigurationSettings.AppSettings["ProviderName"];
Vývojáři stránek jednoduše změní hodnotu atributu <přidání> dílčího prvku <appSettings> do stejného kódu pro přístup k datům, aby mohli přistupovat k jinému úložišti dat, aniž by museli provádět změny v samotném kódu pro přístup k datům.
Obrázek 5 představuje verzi kódu pro přístup k datům (metoda GetSubscribers), která obsahuje nedávné změny.
Obrázek 5 Verze metody GetSubscribers pro extrahování názvu zprostředkovatele a popisného názvu připojovacího řetězce ze souboru web.config
public IEnumerable GetSubscribers()
{
string connectionStringName = ConfigurationSettings.AppSettings["ConnectionStringName"];
string providerName = ConfigurationSettings.AppSettings["ProviderName"];
Configuration configuration = Configuration.GetWebConfiguration("~/");
ConnectionStringsSection section = (ConnectionStringsSection)configuration.Sections["connectionStrings"];
DbProviderFactory provider = DbProviderFactories.GetFactory(providerName);
DbConnection con = provider.CreateConnection();
con.ConnectionString = section.ConnectionStrings[connectionStringName].ConnectionString;
DbCommand com = provider.CreateCommand();
com.Connection = con;
com.CommandText = "Select * From Subscribers";
com.CommandType = CommandType.Text;
DataSet ds = new DataSet();
DbDataAdapter ad = provider.CreateDataAdapter();
ad.SelectCommand = com;
con.Open();
ad.Fill(ds);
con.Close();
return ds.Tables[0].DefaultView;
}
Ovládací prvky zdroje dat
Nejnovější verze metody GetSubscribers, jak je znázorněno na obrázku 5, stále není obecná kvůli následujícím problémům:
- Metoda obsahuje úložiště dat – konkrétní informace, tj. text příkazu a typ příkazu. Vývojáři stránek proto musí metodu ještě před použitím upravit pro přístup k jiné databázi.
- Metoda vrátí instanci DataView třídy svým volajícím tak, aby metoda nasílala své volající tabulková data. Můžeme si to představit jako kontrakt mezi metodou GetSubscribers a jejími volajícími. Volající očekávají, že metoda GetSubscribers bude respektovat smlouvu za všech okolností, i když samotné podkladové úložiště dat není tabulkové. Vzhledem k tomu, GetSubscribers metoda používá ADO.NET objekty pro přístup k podkladovému úložišti dat, nemůže přistupovat k hierarchickému úložišti dat, jako je soubor XML, kde instance tříd v System.Xml a jeho dílčí obory názvů musí být použity místo ADO.NET objekty.
Hlavním problémem s kódem přístupu k datům používaným v metodě GetSubscribers je, že přímo obsahuje skutečný kód, který extrahuje data z podkladového úložiště dat. Přesně to je druh problému, který model zprostředkovatele rozhraní .NET Framework 2.0 je určený speciálně k řešení. Podle vzoru poskytovatele musí metoda GetSubscribers delegovat odpovědnost za poskytnutí kódu pro přístup k úložišti dat do jiné třídy. Označuje se jako třída zprostředkovatele kódu. Typ třídy zprostředkovatele kódu závisí na typu úložiště dat, ke které přistupuje. Tyto třídy zprostředkovatele kódu se souhrnně označují jako ovládací prvky zdroje dat. ASP.NET 2.0 obsahuje několik různých typů ovládacích prvků zdroje dat, včetně sqlDataSource, AccessDataSource, ObjectDataSource, XmlDataSourcea Ovládací prvky SiteMapDataSource.
Ovládací prvek SqlDataSource je speciálně navržený tak, aby aktualizoval, odstranil, vložil a extrahovali data z relačních úložišť dat, jako je Microsoft SQL Server a Oracle. Ovládací prvek AccessDataSource je podtřídou ovládacího prvku SqlDataSource, který ví, jak pracovat s databázemi Microsoft Accessu. Ovládací prvek ObjectDataSource na druhé straně používá obchodní objekty v paměti jako své úložiště dat. Ovládací prvek XmlDataSource je speciálně určen k extrakci dat z dokumentů XML. Ovládací prvek XmlDataSource však neposkytuje přístup k zápisu do podkladového dokumentu XML.
Každý ovládací prvek zdroje dat zveřejňuje jedno nebo více zobrazení příslušného úložiště dat. Každé zobrazení je instance příslušné třídy. Například ovládací prvky SqlDataSource, AccessDataSource a ObjectDataSource zpřístupňují zobrazení, která jsou instancemi SqlDataSourceView, AccessDataSourceViewa ObjectDataSourceView třídy. Zobrazení skrývají skutečný typ podkladového úložiště dat a chovají se jako typ, který očekává kód pro přístup k datům. Metoda GetSubscribers například očekává tabulkový typ úložiště dat, protože odesílá tabulková data klientům. Tabulkové zobrazení umožňují metodu GetSubscribers extrahovat tabulková data z podkladového úložiště dat i v případě, že samotné úložiště dat je hierarchický zdroj dat, například dokument XML. To umožňuje metodu GetSubscribers považovat tabulkové i hierarchické úložiště dat za tabulkové úložiště dat.
Ovládací prvky zdroje dat můžou svým klientům poskytnout dva typy zobrazení: tabulkové a hierarchické. ASP.NET 2.0 obsahuje dva ovládací prvky zdroje dat, které poskytují oba typy zobrazení, XmlDataSource a SiteMapDataSource. Zbývající ovládací prvky zdroje dat – SqlDataSource, AccessDataSource a ObjectDataSource – představují pouze tabulková zobrazení. Lze je ale rozšířit tak, aby poskytovaly tabulkové i hierarchické zobrazení.
Ovládací prvky tabulkového zdroje dat
Ovládací prvek zdroje tabulkových dat chová své podkladové úložiště dat jako tabulkové úložiště dat bez ohledu na to, jestli je úložiště dat tabulkové. Tabulkové úložiště dat se skládá z tabulek řádků a sloupců, kde každý řádek představuje položku dat. Název tabulky jednoznačně identifikuje a vyhledá tabulku mimo jiné tabulky v tabulkovém úložišti dat. Tabulkové zobrazení funguje jako tabulka, což znamená, že jsou pojmenována zobrazení.
Jak je popsáno dříve, každá třída správy zdrojů dat a její přidružená třída zobrazení (např. Třída SqlDataSource a její přidružená třída SqlDataSourceView) poskytují skutečný kód pro aktualizaci, odstranění, vložení a extrahování dat z podkladového úložiště dat. Kód pro každou správu zdroje dat a jeho přidružená třída zobrazení je samozřejmě navržena tak, aby fungovala s konkrétním typem úložiště dat. Proto každá třída správy zdroje dat a její přidružená třída zobrazení jsou specifické pro úložiště dat. To představuje závažný problém s metodou GetSubscribers, která používá ovládací prvky zdroje dat a jejich tabulková zobrazení pro přístup k podkladovému úložišti dat, protože spojuje metodu s konkrétním typem úložiště dat, což znamená, že stejnou metodu nelze použít pro přístup k různým typům úložišť dat.
ASP.NET 2.0 nabízí řešení, které používá model poskytovatele k:
- Představení IDataSource rozhraní a DataSourceView abstraktní třídy
- Odvození všech ovládacích prvků tabulkového zdroje dat z rozhraní IDataSource
- Odvození všech tabulkových zobrazení z abstraktní třídy DataSourceView
IDataSource rozhraní a DataSourceView abstraktní třída delegují odpovědnost za poskytnutí skutečného kódu pro aktualizaci, odstranění, vložení a extrahování dat z úložiště dat do příslušných podtříd. Kód přístupu k datům, jako je GetSubscribers metoda, musí používat metody a vlastnosti rozhraní IDataSource a DataSourceView abstraktní třídy. Nesmí používat žádnou metodu nebo vlastnost specifickou pro konkrétní třídu správy zdrojů dat, jako je SqlDataSource nebo konkrétní třída zobrazení zdroje dat, jako je SqlDataSourceView. Model zprostředkovatele umožňuje kódu přístupu k datům zacházet se všemi ovládacími prvky zdroje dat a jejich příslušnými zobrazeními zdrojů dat obecným způsobem. Pokud jde o kód pro přístup k datům, všechny ovládací prvky zdroje dat jsou typu IDataSource a všechna zobrazení zdroje dat jsou typu DataSourceView. Kód pro přístup k datům nemá žádný způsob, jak zjistit skutečný typ ovládacího prvku zdroje dat a objektu zobrazení zdroje dat. To způsobí nový problém. Pokud kód přístupu k datům (metoda GetSubscribers) nezná typ ovládacího prvku zdroje dat, jak může vytvořit instanci?
Jak je popsáno dříve, model poskytovatele poskytuje řešení, které se skládá z následujících kroků:
- Jedinečné ID řetězce slouží k identifikaci jednotlivých tříd správy zdrojů dat.
- Textový soubor (obvykle soubor XML) slouží k ukládání informací o všech třídách správy zdrojů dat.
- Mechanismus je navržen a implementován, který prohledá soubor XML podtřídu s daným ID řetězce.
Teď se podívejme, jak ASP.NET 2.0 implementuje výše uvedené tři úlohy modelu poskytovatele. ASP.NET 2.0 odvozuje všechny ovládací prvky zdroje dat z třídy Control. Proč se ovládací prvky zdroje dat odvozují z třídy Control, pokud nevykreslují text kódu HTML? Odvozují z třídy Control, aby mohly dědit následující tři důležité funkce:
- Lze je vytvořit deklarativním způsobem.
- Ukládají a obnovují své hodnoty vlastností napříč zpětnými příspěvky.
- Jsou přidány do řídicího stromu obsahující stránky.
První funkce umožňuje vývojářům stránek deklarativní vytváření instancí ovládacích prvků zdroje dat v příslušných .aspx souborech. Soubor .aspx proto funguje jako textový soubor nebo soubor XML, který vyžaduje druhý krok vzoru zprostředkovatele. Architektura ovládacího prvku ASP.NET 2.0 dynamicky vytvoří instanci deklarovaného ovládacího prvku zdroje dat a přiřadí instanci proměnné, jejíž název je hodnota vlastnosti ID deklarovaného ovládacího prvku zdroje dat. To se postará o výše uvedené první a třetí kroky, které model poskytovatele vyžaduje.
Obrázek 6 znázorňuje verzi metody GetSubscribers, která používá metody a vlastnosti rozhraní IDataSource a Abstraktní třída DataSourceView pro přístup k podkladovému úložišti dat:
Obrázek 6 Verze GetSubscribers metoda, která používá metody a vlastnosti IDataSource rozhraní a DataSourceView abstraktní třídy
void GetSubscribers()
{
IDataSource ds = (IDataSource)MySource;
DataSourceView dv = ds.GetView(String.Empty);
DataSourceSelectArguments args = new DataSourceSelectArguments();
if (dv.CanSort)
args.SortExpression = "Email";
DataSourceViewSelectCallback callback = new DataSourceViewSelectCallback(SendMail);
dv.Select(args, callback);
}
První řádek GetSubscribers metoda jasně ukazuje, že metoda považuje řízení zdroje dat za objekt typu IDataSource. Metoda není a neměla by se starat o skutečný typ ovládacího prvku zdroje dat, například zda se jedná o SqlDataSource, AccessDataSource, ObjectDataSource nebo XmlDataSource ovládacího prvku. To umožní vývojářům stránek přepnout z jednoho ovládacího prvku zdroje dat na jiný, aniž by museli upravovat kód přístupu k datům (metoda GetSubscribers). V další části najdete další informace o tomto důležitém problému.
GetSubscribers metoda volá GetView metoda IDataSource objekt pro přístup k jeho výchozí tabulkové zobrazení objektu. Všimněte si GetView metoda vrací objekt typu DataSourceView. GetSubscribers metoda není a neměl by se starat o skutečný typ objektu view, jako je například SqlDataSourceView, AccessDataSourceView, ObjectDataSourceView nebo XmlDataSourceView objektu.
Dále Metoda GetSubscribers vytvoří instanci DataSourceSelectArguments třídy pro vyžádání dalších operací, jako je vložení, stránkování nebo načtení celkového počtu řádků na datech, která Select operace vrátí. Metoda nejprve musí zkontrolovat hodnotu CanInsert, CanPage, nebo CanRetrieveTotalRowCount vlastnost DataSourceView třídy, aby se před provedením požadavku zajistilo, že objekt zobrazení podporuje příslušnou operaci.
Vzhledem k tomu, že operace Select je asynchronní, metoda GetSubscribers zaregistruje metodu SendMail jako zpětné volání. Metoda Select automaticky volá metodu SendMail po dotazování na data a předá data jako argument, jak je znázorněno na obrázku 7.
Obrázek 7 Metoda SendMail vytvoří výčet dat a extrahuje potřebné informace.
void SendMail(IEnumerable data)
{
string firstName = String.Empty;
string lastName = String.Empty;
IEnumerator iter = data.GetEnumerator();
while (iter.MoveNext())
{
MailMessage message = new MailMessage();
message.From = "admin@greatnews.com";
message.To = DataBinder.Eval(iter.Current, "Email").ToString();
message.Subject = "NewsLetter";
firstName = DataBinder.Eval(iter.Current, "FirstName").ToString();
lastName = DataBinder.Eval(iter.Current, "LastName").ToString();
string mes = "Dear " + firstName + " " + lastName + ",<br/>";
mes += MessageBody.Text;
message.Body = mes;
message.BodyFormat = MailFormat.Html;
SmtpMail.SmtpServer = "<myserver>";
SmtpMail.Send(message);
}
}
Metoda SendMail volá GetEnumerator metodu objektu předaného jako jeho první argument pro přístup k objektu enumerátoru a používá enumerátor k vytvoření výčtu dat. Metoda SendMail používá metodu Eval třídy DataBinder k extrahování e-mailové adresy, křestního jména a příjmení každého odběratele a posílá zprávy každému z nich.
Přepnutí z jednoho ovládacího prvku zdroje dat na jiný
Jak je popsáno dříve, architektura ASP.NET ovládacího prvku dynamicky vytvoří instanci ovládacího prvku zdroje dat deklarované na příslušné stránce .aspx a přiřadí ji proměnné, jejíž název je hodnota ID vlastnost deklarovaného ovládacího prvku zdroje dat. Taková dynamická instance deklarovaného ovládacího prvku zdroje dat izoluje Metodu GetSubscribers od skutečného typu ovládacího prvku zdroje dat a umožňuje metodě zacházet se všemi ovládacími prvky zdroje dat jako s objekty typu IDataSource. Vývojáři stránek tak můžou přejít z jednoho typu ovládacího prvku zdroje dat na jiný beze změny kódu přístupu k datům (metoda GetSubscribers). Tato část představuje příklad takového případu.
Řekněme, že naše webová aplikace používá metodu GetSubscribers ve spojení s ovládacím prvku ObjectDataSource k načtení seznamu odběratelů z relačního úložiště dat, jako je Například Microsoft SQL Server:
<asp:SqlDataSource ID="MySource" Runat="Server"
ConnectionString="<%$ ConnectionStrings:MySqlConnectionString %>"
SelectCommand="Select * From Subscribers" />
Předpokládejme, že naše webová aplikace funguje v prostředí, kde seznam odběratelů může pocházet také z dokumentu XML. Dokument XML může být místní soubor XML nebo vzdálený prostředek přístupný přes adresu URL. Proto musí být naše aplikace schopná načíst seznam odběratelů z dokumentů XML. Samozřejmě ObjectDataSource ovládací prvek není určen k načtení tabulkových dat z dokumentů XML, což znamená, že musíme použít ovládací prvek zdroje dat, který může načíst tabulková data z dokumentů XML, například XmlDataSource ovládacího prvku.
Metoda GetSubscribers nepoužívá žádnou vlastnost nebo metodu specifickou pro ObjectDataSource a ObjectDataSourceView třídy a používá pouze metody a vlastnosti rozhraní IDataSource a DataSourceView abstraktní třídy pro zpracování ovládacích prvků zdroje dat. Můžeme snadno přepnout z ObjectDataSource do ovládacího prvku XmlDataSource a použít stejný přístupový kód dat jako GetSubscribers metoda načtení seznamu odběratelů:
<asp:XmlDataSource ID="MySource" Runat="Server"
DataFile="data.xml" XPath="/Subscribers/Subscriber" />
Hodnota atributu XPath ovládacího prvku XmlDataSource je nastavena na /Subscribers/Subscriber pro výběr všech odběratelů.
Operace vložení a odstranění
Vzpomeňte si, že naše webová aplikace se skládá ze dvou částí. Druhá část aplikace umožňuje uživatelům přihlásit se k odběru nebo odhlášení odběru ze seznamu adresátů. Metoda Přihlásit k odběru se volá, když kliknete na tlačítko Přihlásit k odběru, jak je znázorněno na obrázku 8.
Obrázek 8 Metoda Přihlášení k odběru se volá při kliknutí na tlačítko Přihlásit k odběru.
void Subscribe(Object sender, EventArgs e)
{
IDataSource ds = (IDataSource)MySource;
DataSourceView dv = ds.GetView(String.Empty);
KeyedList values = new KeyedList();
values.Add("Email", Email.Text);
values.Add("FirstName", FirstName.Text);
values.Add("LastName", LastName.Text);
DataSourceViewOperationCallback callback = new DataSourceViewOperationCallback(OperationCallback);
if (dv.CanInsert)
dv.Insert(values, callback);
}
První řádek metody Subscribe ukazuje, že metoda se nezajímá o skutečný typ ovládacího prvku zdroje dat. Proto můžeme přepnout na jinou správu zdrojů dat, abychom podporovali nové úložiště dat, aniž bychom museli měnit kód v metodě Přihlášení k odběru.
Metoda používá instanci KeyedList třídy ke shromáždění e-mailu, křestního jména a příjmení odběratele. Nemusíme používat třídu KeyedList. Můžeme použít libovolnou třídu, která implementuje rozhraní IDictionary, včetně ArrayList, KeyedList atd.
Metoda Subscribe zkontroluje hodnotu CanInsert vlastnosti objektu zobrazení zdroje dat, aby se zajistilo, že objekt zobrazení podporuje operaci Insert předtím, než zavolá metodu Insert. Metoda Subscribe předá instanci KeyedList jako první argument metodě Insert.
Metoda Odhlášení odběru funguje podobně jako metoda Přihlášení k odběru. Hlavním rozdílem je, že metoda odhlášení odběru volá metodu Delete příslušného objektu zobrazení, aby se odběr odebral z podkladového úložiště dat, jak je znázorněno na obrázku 9.
Obrázek 9 Metoda odhlášení odběru se volá po kliknutí na tlačítko Odhlásit odběr.
void Unsubscribe(Object sender, EventArgs e)
{
IDataSource ds = (IDataSource)MySource;
DataSourceView dv = ds.GetView(String.Empty);
KeyedList keys = new KeyedList();
keys.Add("Email", Email.Text);
KeyedList oldValues = new KeyedList();
oldValues.Add("Email", Email.Text);
DataSourceViewOperationCallback callback = new DataSourceViewOperationCallback(OperationCallback);
if (dv.CanDelete)
dv.Delete(keys, oldValues, callback);
}
Hierarchické ovládací prvky zdroje dat
Metoda GetSubscribers (kód pro přístup k datům) předá tabulková data svým volajícím. V době, kdy ale kód pro přístup k datům musí vrátit hierarchická data svým volajícím. Tato část představuje implementaci verze GetSubscribers metoda, která vrací hierarchická data. Můžeme si to představit jako smlouvu mezi metodou a jejími volajícími. Volající očekávají, že metoda vrátí hierarchická data z hierarchických i tabulkových úložišť dat.
ASP.NET 2.0 používá model zprostředkovatele k izolaci metody GetSubscribers od skutečného typu podkladového úložiště dat a představuje metodu s hierarchickými zobrazeními úložiště dat. Tato metoda umožňuje zpracovávat hierarchické i tabulkové úložiště dat jako hierarchické úložiště dat.
Každá hierarchická správa zdrojů dat je speciálně navržená tak, aby fungovala s konkrétním úložištěm dat. Vzhledem k tomu, že všechny hierarchické ovládací prvky zdroje dat implementují IHierarchicalDataSource rozhraní a všechna hierarchická zobrazení zdroje dat odvozená z HierarchicalDataSourceView třídy, Metoda GetSubscribers nemusí řešit specifika každého ovládacího prvku zdroje dat a může s nimi pracovat obecně.
IHierarchicalEnumerable GetSubscribers()
{
IHierarchicalDataSource ds = (IHierarchicalDataSource)MySource;
HierarchicalDataSourceView dv = ds.GetHierarchicalView("/Subscribers");
return dv.Select();
}
První řádek GetSubscribers metoda ukazuje, že metoda považuje řízení zdroje dat za objekt typu IHierarchicalDataSource a nezajímá skutečný typ správy zdroje dat. Vývojáři stránek tak můžou přejít na novou hierarchickou správu zdrojů dat a přidat podporu pro nové úložiště dat, aniž by museli upravovat kód v metodě GetSubscribers.
GetSubscribers metoda pak volá GetHierarchicalView metodu HierarchicalDataSourceView pro přístup k hierarchickému zobrazení s danou cestou, například "/Subscribers". Všimněte si, že metoda Select není asynchronní. Aplikace předá data vrácená metodou GetSubscribers metodě SendMail (viz obrázek 15). Všimněte si, že data jsou typu IHierarchicalEnumerable.
IHierarchicalEnumerable implementuje IEnumerable, což znamená, že zveřejňuje GetEnumerator metoda. Metoda SendMail volá GetEnumerator metoda pro přístup k příslušné IEnumerator objektu, který se následně používá k vytvoření výčtu dat. IHierarchicalEnumerable také zveřejňuje metodu s názvem GetHierarchyData, která vezme výčtový objekt a vrátí IHierarchyData objekt přidružený k němu.
IHierarchyData rozhraní zveřejňuje důležitou vlastnost s názvem Item, což není nic jiného než datová položka. Metoda SendMail používá metodu Eval třídy XPathBinder k vyhodnocení výrazů XPath proti item objektu.
Obrázek 10 Metoda SendMail vytvoří výčet dat, extrahuje potřebné informace a odešle bulletin každému odběrateli.
void SendMail(IHierarchicalEnumerable data)
{
string firstName = String.Empty;
string lastName = String.Empty;
IEnumerator iter = data.GetEnumerator();
while (iter.MoveNext())
{
IHierarchyData ihdata = data.GetHierarchyData(iter.Current);
MailMessage message = new MailMessage();
message.From = "admin@subscribers.com";
message.To = XPathBinder.Eval(ihdata.Item, "@Email").ToString();
message.Subject = "NewsLetter";
firstName = XPathBinder.Eval(ihdata.Item, "@FirstName").ToString();
lastName = XPathBinder.Eval(ihdata.Item, "@LastName").ToString();
string mes = "Hi " + firstName + " " + lastName + ",<br/>";
mes += MessageBody.Text;
message.Body = mes;
message.BodyFormat = MailFormat.Html;
SmtpMail.SmtpServer = "MyServer";
SmtpMail.Send(message);
}
}
Závěr
Pomocí podrobného přístupu, který ukazuje různé nástroje a techniky ASP.NET 2.0 a ADO.NET 2.0, tento článek ukazuje, jak můžou vývojáři stránek psát obecný kód pro přístup k datům, který lze použít pro přístup k různým typům úložišť dat.
Dr. Shahram Khosravije vedoucí softwarový inženýr se Schlumberger Information Solutions (SIS). Shahram se specializuje na ASP.NET, webové služby XML, technologie .NET, technologie XML, 3D počítačové grafiky, hi/použitelnost, vzory návrhu a vývoj ASP.NET serverových ovládacích prvků a komponent. Má více než 10 let zkušeností s objektově orientovaným programováním. Používá různé nástroje a technologie Microsoftu, jako je SQL Server a ADO.NET. Shahram napsal články o technologiích .NET a ASP.NET pro časopis asp.netPRO.