https://msdn.microsoft.com/zh-cn/library/ms971499.aspx

http://www.c-sharpcorner.com/UploadFile/mosessaur/abstractfactoryadonet202152006053643AM/abstractfactoryadonet2.aspx

Introduction

Most Web applications contain data access code to access the underlying data store to perform basic data operations such as SelectUpdateDelete, and Insert.

大多数web应用包含了数据访问的代码,来访问底层数据存储。基础的数据操作有,筛选,更新,删除,插入【增删改查】

This article uses a step-by-step approach to show how page developers can take advantage of different ASP.NET 2.0 and ADO.NET 2.0 tools and techniques to write generic data access code that can be used to access different types of data stores.

这篇文章通过一步一步的方式来展示,页面开发者如何利用ASP.NET 2.0 和 ADO.NET 2.0中不同的工具和技术来写泛型的数据访问代码,这些代码可以用来访问不同类型的数据存储。

Writing generic data access code is especially important in data-driven Web applications because data comes from many different sources, including Microsoft SQL Server, Oracle, XML documents, flat files, and Web services, just to name a few.

在web应用中,写泛型数据访问代码是相当重要的,因为数据来自于不同的数据源,简单的举例:MS SQL Server,Oracle,XML文档,flat文件,web服务。

This article uses a simple Web application as a test bed for all the code presented here.

这篇文章使用简单的web应用作为测试,所有的代码都展示在这里。

The application consists of two parts: the first part allows the system administrator to send newsletters to all subscribers of a mailing list.

这个应用包含2个部分:第一部分允许系统管理员发送时事通讯给邮件列表中的所有订阅者。

The second part allows users to subscribe or unsubscribe from a mailing list.

第二部分允许用户注册到邮件列表,或者从邮件列表注销

The first part of the article begins by implementing a simple data access code (see Figure 1) to access Microsoft SQL Server and extract the list of subscribers.

文章的第一部分通过实现一个的数据访问代码来访问MS SQL Server,并且提取出订阅者列表。

The code is modified and made more generic over the course of the article.

代码将会被修改,并在整个文章的过程中变得更为通用。

Figure 1. The GetSubscribers method extracts the list of all subscribers.   通过GetSubscribers方法提取所有的订阅者列表

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[].DefaultView;
}

Since the data access code in Figure 1 contains code for creating the ADO.NET objects, such as the SqlConnectionSqlCommand, and SqlDataAdapter instances.

Figure 1中的数据访问代码包含了创建ADO.NET对象的代码,例如SqlConnection,SqlCommand,SqlDataAdapter实例。

The data access code cannot be used to retrieve the list of subscribers from other data stores, such as an Oracle database.

数据访问代码不能用来从其他数据存储中检索订阅者列表,比如Oracle数据库

Page developers have to modify the data access code (using the GetSubscribers method) every time they need to access a new data store.

每一次需要访问一个新的数据存储的时候,页面开发者都需要修改数据访问代码(使用GetSubscribers方法)

Next, see how ADO.NET 2.0 uses the provider pattern to help page developers write generic data access code to access different types of data stores.

下一步,来看看ADO.NET 2.0 是如何使用provider模式来帮助页面开发者,写出泛型数据访问代码来访问不同类型的数据存储

=========================================================================================================================================

Provider Pattern in ADO.NET 2.0  ADO.Net2.0中的提供者模式

The main problem with the GetSubscribers method is that it contains the code for creating the ADO.NET objects.

GetSubscribers 方法的主要问题在于它包含了创建ADO.NET对象的代码

According to the provider pattern, the data access code must delegate the responsibility of providing the code for creating the ADO.NET objects to another class.  代码提供者类

根据提供者模式,数据访问代码必须将负责创建ADO.NET对象的代码交给另外一个类取实现

I refer to this class as the "code provider class" because it provides the code for creating the ADO.NET objects.

我将这个类归为"代码提供者类",因为它提供代码来创建ADO.NET对象

The code provider class exposes methods such as CreateConnectionCreateCommand, and CreateDataAdapter, where each method provides the code for creating the corresponding ADO.NET object.

代码提供者类暴露一些方法来创建一致的ADO.Net对象,例如:CreateConnection,CreateCommand,CreateDataAdapter

Since the code provider class contains the actual code, the same class cannot be used to access different data stores.

由于代码提供者类包含了实际的代码,同一个代码提供者不能用来访问不同的数据存储

Therefore, the data access code (the GetSubscribers method) has to be modified and reconfigured to delegate the responsibility of providing the code to a new code provider class each time it is used to access a new data store.

所以,数据访问代码(GetSubscribers方法)每一次用来访问一个新的数据存储的时候,就需要修改和重新配置数据访问代码,将提供代码的职责分配给一个新的"代码提供者类"

The GetSubscribers method is still tied to the code even though it does not contain the code.

GetSubscribers方法仍然被绑定在代码上,即使它不包含创建ADO.Net对象的代码

The provider pattern offers a solution to this problem and consists of the following steps:提供者模式提供了一种方案来解决这个问题,包含以下步骤

  1. Design and implement an abstract base provider class.  步骤1:设计并实现一个抽象的提供者基类
  2. Derive all code provider classes from the abstract base provider class.  步骤2:从这个基类派生所有的"代码提供者类"
  3. Have the data access code (the GetSubscribers method) to use the abstract base class instead of the individual code provider classes.

步骤3:有一个数据访问代码(GetSubscribers方法),使用抽象的基类而不是独立的代码提供者类

The abstract base class delegates the responsibility of providing the code for creating the ADO.NET objects to the appropriate subclass. The abstract base class is named DbProviderFactory. The following presents some of the methods of this class:

抽象的基类将"负责创建ADO.NET对象的代码"分派到合适的子类中,抽象的基类被称为DbProviderFactory。下面展示了这个类的部分方法

public abstract class DbProviderFactory
{
public virtual DbConnection CreateConnection();
public virtual DbCommand CreateCommand();
public virtual DbDataAdapter CreateDataAdapter();
}

Each subclass provides the code for creating the appropriate ADO.NET objects for a particular data store.

每一个子类为一个特定的数据存储提供代码来创建合适的ADO.NET对象

For instance, the SqlClientFactory subclass provides the code for creating the ADO.NET objects to access Microsoft SQL Server, as shown in Figure 2.

例如,SQLClientFactory子类,提供了代码来创建ADO.Net对象来访问MS SQL Server数据库。

==============================================================================================================================

Figure 2. The SqlClientFactory class and some of its methods   SqlClientFactory类以及它的一些方法

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();
}
}

The provider pattern allows the data access code to treat all the subclasses the same because they are all subclasses of the same base class.

提供者模式允许数据访问代码以相同的方式对待所有的子类,因为他们都派生自同一个父类。

As far as the data access code is concerned, all subclasses are of type DbProviderFactory.

就数据访问代码而言,所有的子类都是DbProviderFactory类型

The data access code has no way of knowing the specific type of the subclass being used.This introduces a new problem.

数据访问代码没办法知道哪一个特定的子类被使用了,这就导致了一个新的问题

If the data access code (the GetSubscribers method) does not know the type of subclass, how can it then instantiate an instance of the subclass?

如果数据访问代码(GetSubscribers方法)不知道子类的类型,那么它如何实例化一个子类的实例呢?

The provider pattern solution to this problem consists of the following three parts:   //解决这个问题的方案包括一下3个步骤

  • 1.A unique string is used to identify each subclass. ADO.NET 2.0 uses the namespace of the subclass as its unique string id. For instance, the unique string id's System.Data.SqlClient andSystem.Data.OracleClient identify SqlClientFactory and OracleClientFactory subclasses, respectively.

步骤1:使用一个独一无二的字符串用来识别每一个子类。 在ADO.Net通过子类所在的命令空间作为子类独一无二的字符串编号。例如独一无二的字符串编号:System.Data.SqlClient ,System.Data.OracleClient分别用来识别SQLClientFactory和OracleClientFactory这2个子类

  • 2.A text file (normally an XML file) is used to store information about all the subclasses. ADO.NET 2.0 uses the machine.config and web.config files to store the required information. The information about a subclass contains, among other things, the unique string id and the name of the type of the subclass. For instance, the information about the SqlClientFactory subclass includes the unique string idSystem.Data.SqlClient and the name of the type of the subclass, i.e., System.Data.SqlClient.SqlClientFactory.

步骤2:一个文本文件用来存储所有子类的信息,通常以xml的形式来存储。  ADO.NET 2.0 使用machine.config和web.config来保存需要的信息。除了子类的信息外还包括唯一的字符串编号以及子类的类型名称。

例如:SqlClientFactory 的子类包括独一无二的字符串编号System.Data.SqlClient,子类的类型名称是System.Data.SqlClient.SqlClientFactory

  • 3.A static method is designed and implemented. The method could be part of the abstract base class or part of a separate class. ADO.NET 2.0 uses a separate class named DbProviderFactories that exposes theGetFactory static method. The method takes the unique string id of the desired subclass as its only argument and searches through the machine.config file for a subclass with the given unique string id. The method extracts the name of the type of the desired subclass and uses reflection to dynamically create an instance of the subclass.

步骤3:需要设计并实现一个静态方法。这个静态方法可以是抽象基类的一部分,也可以是一个独立的类的一部分。在ADO.Net2.0中使用了一个独立的类DbProviderFactories,提供了一个GetFactory的静态方法。

此方法将所需的子类的独一无二的字符串编号作为它唯一的参数,并且用它从machine.config中查找子类。

此方法提取了所需子类的类型名称,并使用反射动态的创建子类的实例。

Data access code (the GetSubscribers method) calls the GetFactory static method and passes the appropriate unique string id to access the instance of the corresponding subclass.

数据访问代码(GetSubscribers 方法)调用GetFactory 这个静态方法,并传递合适的独一无二的字符串编号来获取对应的子类的实例。

After the GetSubscribers method accesses the instance, it calls the appropriate creation methods, such as CreateConnection(), CreateCommand(), etc., to instantiate the appropriate ADO.NET objects, as shown in Figure 3.

在GetSubscribers方法获取了子类的实例后,它会调用合适创建方法,例如CreateConnection,CreateCommand等等,来实例化合适的ADO.NET对象

===============================================================================================================================================

Figure 3. The version of the GetSubscribers method that uses the new ADO.NET provider pattern   使用ADO.Net提供者模式的GetSubscribers 方法的新版本

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[].DefaultView;
}

The data access code (the GetSubscribers method) delegates the responsibility of providing the code for creating the ADO.NET objects to the code provider class instance that the GetFactory method instantiates and returns.

数据访问代码(GetSubscribers 方法)将创建ADO.Net对象的职责分配给了代码提供者类的实例,这个实例是通过GetFactory 方法实例化并返回的

Therefore, the same data access code can be used to access different data stores, such as Microsoft SQL Server and Oracle.

所以,数据访问代码可以用同样的方法来访问不同的数据存储,例如MS SQL Server和Oracle

The code for creating the right ADO.NET objects is data-store–specific. 创建正确的ADO.Net对象是 data-store–specific

The provider pattern in ADO.NET 2.0 removes these data-store–specific parts from the data access code (the GetSubscribers method) to make it more generic.

ADO.Net2.0的提供者模式将data-store–specific部分从数据访问代码(GetSubscribers方法)移除使得它变得更泛型。

However, the provider pattern does not remove all the data-store–specific parts.

然而,提供者模式并没有移除所有的data-store–specific部分

Closer inspection of the GetSubscribers method reveals the following remaining data-store–specific parts:

进一步的检查GetSubscribers 方法可以发现仍然有以下data-store–specific部分

  1. Connection string    连接字符串
  2. Unique string id that identifies the underlying code provider class    用来识别底层的"代码提供者类"的独一无二的字符串编号
  3. Command text      命令文本
  4. Command type      命令类型

Unless something is done about the above parts, the data access code is still tied to a particular type of data store.

除非做一些事情来解决上述问题,否则数据访问代码仍然被绑定在特定的数据存储类型上

The provider pattern in ADO.NET 2.0 does not help with this problem.

ADO.Net2.0中提供者模式并没有帮助解决这个问题

However, ADO.NET 2.0 provides us with other tools and techniques to remove the first two data-store–specific parts, such as the connection string and unique string id from the GetSubscribers method.

然而ADO.Net2.0提供了其他工具和技术来移除前2个data-store–specific 的部分,例如GetSubscribers 方法中的连接字符串和独一无二的字符串编号(命名空间)

Connection Strings   连接字符串

Connection strings are some of the most valuable resources in a Web application.     在web应用中,连接字符串是最有价值的资源

They are so important that the .NET Framework 2.0 treats them as "first-class citizens".     它们是如此的重要,以致与.net2.0将它们作为"first-class citizens"来对待

The web.config file now supports a new section named <connectionStrings> that contains all the connection strings used in an application.

web.config文件现在支持一个名为connectionStrings的节点,此节点可以包含在一个应用中使用到的所有连接字符串。

Therefore, we will move the connection string from the GetSubscribers method to this section:

因此,我们把连接字符串从GetSubscribers 方法中移动到配置文件中的connectionStrings节点中

<?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>

The <add> subelement of the <connectionStrings> element exposes the following three important attributes:

connectionStrings元素的子元素add包含以下三个重要的属性

  • Name—The friendly name of the connection string    连接字符串的友好名称(易记的)
  • connectionString—The actual connection string       实际的连接字符串
  • providerName—The unique string id or invariant of the code provider class    独一无二的字符串编号或不变的"代码提供者类"

NET Framework 2.0 provides the data access code (the GetSubscribers method) with the right tools to generically extract the connection string value from the web.config file as described in the following.

.net2.0给数据访问代码提供了准确的工具来通用地提取连接字符串,按照下面所描述的方式从web.config文件中提取。

TheSystem.Configuration namespace in .NET Framework 2.0 includes a new class named Configuration.

在.net2.0中,System.Configuration命名空间下包含了一个名为Configuration的新类

This class represents the entire content of a web.config or machine.config file.

这个类代表了web.config或者machine.config文件的所有内容

The data access code cannot use the new operator to directly create an instance of this class.

数据访问代码无法通过new操作符直接地创建此类的实例

The class itself exposes a static method named GetWebConfiguration that takes the path to the web.config file and returns an instance of the Configuration class that represents the entire contents of the web.config file:

Configuration类公开了一个名为GetWebConfiguration 的静态方法,它可以访问web.config文件,并返回一个Configuration类的实例,这个实例包含了web.config文件的所有内容

Configuration configuration = Configuration.GetWebConfiguration("~/");

A class that inherits from the ConfigurationSection class represents every section of the web.config file.

ConfigurationSection 派生的类,代表了web.config文件中的每一个节点

The name of the class consists of the name of the section plus the keyword Section.

派生类的类名由节点名称+Section关键字组成。

For instance, the ConnectionStringsSection class represents the content of the <connectionStrings> section of the web.config file.

例如,ConnectionStringsSection 类,代表了web.config文件中connectionStrings的节点内容

The data access code (the GetSubscribers method) cannot use the new operator to directly create an instance of the ConnectionStringsSection class.

数据访问代码,无法使用new操作法直接创建ConnectionStringsSection类的实例

The Configuration class exposes a collection property named Sections that contains all the objects that represent different sections of the web.config file:

Configuration 类公开了一个名为Sections 的集合属性,包含了web.config文件中的不同的节点对象    Sections属性的类型是ConfigurationSectionCollection,类似于字典的键值对

ConnectionStringsSection section = (ConnectionStringsSection)configuration.Sections["connectionStrings"];

Since Sections is a collection of ConfigurationSection objects, the data access code must type cast the returned instance. After the GetSubscribers method accesses the ConnectionStringsSection object and uses it to access the connection string value:

由于Sections是一个ConfigurationSection 的集合对象,数据访问代码肯定可以通过返回的对象进行类型转换。在GetSubscribers 方法得到了ConnectionStringsSection 对象后,就可以用它来获取连接字符串的值

string connectionString = section.ConnectionStrings["MySqlConnectionString"].ConnectionString;

============================================================================================================================================

Figure 4 shows the new version of the GetSubscribers method that contains the required code to extract the connection string in generic fashion.

GetSubscribers 方法的新版本:用通用的代码风格来提取连接字符串

Figure 4. The version of the GetSubscribers method that extracts the connection string from the web.config file

public IEnumerable GetSubscribers()
{
DbProviderFactory provider = DbProviderFactories.GetFactory("System.Data.SqlClient"); Configuration configuration = Configuration.GetWebConfiguration("~/");
ConnectionStringsSection section = (ConnectionStringsSection)configuration.Sections["connectionStrings"]; DbConnection con = provider.CreateConnection();
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;
}

The GetSubscribers method now includes the MySqlConnectionString string, so we still have to modify the GetSubscribers method to add support for a different data store such as Oracle database.

GetSubscribers 方法现在包含了MySqlConnectionString字符串,所以我们仍然不得不修改GetSubscribers方法来增加对不同的数据存储的支持,例如Oracle

It would seem that we are back to square one. Not really. We have gained a few important benefits by moving the connection string from the data access code to the web.config file:

看起来我们又回到了原点。但并非如此。通过把连接字符串移动从GetSubscribers 移动到web.config文件中,我们已经获取了一点非常重要的好处。

  • 1.The connection string is now the value of the connectionString attribute of the <add> sub element of the connectionStrings element of the web.config file, which is an XML document.

连接字符串现在是  web.config文件中connectionStrings 元素的子元素add的属性connectionString的值,web.config文件是一个xml文件。

The great thing about an XML document is that we can encrypt a single element in the document. We do not have to encrypt the entire document if we only need to protect small part of it.

xml文件最棒的一点是,我们对文件中的单个元素进行加密。如果我们只要保护文件中的小部分内容,那么我们就无需加密整个文件。

The .NET Framework 2.0 comes with a tool that allows us to encrypt the <connectionStrings> section to protect our most important resource, the connection strings.

.net2.0提供了一个工具来让我们对<connectionStrings>节点进行加密来包换我们重要的资源,连接字符串。

Imagine how much damage a hacker can do to our valuable database if he gets his hand on our connection strings. Remember connection strings are all a hacker needs to access our database.

如果一个黑客得到了我们一个有价值的数据库的连接字符串,他能够造成多大的破坏。记住黑客访问我们的数据库所需要的仅仅是连接字符串。

2.It may seem that all we have done is to replace the following string

"Data Source=.\SQLExpress;Integrated Security=True;AttachDBFilename=D:\Application\Data\Database.mdf"

with the new string, MySqlConnectionString.

看起来我们所要做的是用一个新的字符串来替换之前的字符串

However, there is one big difference. The former string contains the SQL Server database-specific information that does not apply to another database such as Oracle, but the latter string is just a friendly name.

然而,这有很大的不同。前面的字符串包含了SQLServer数据库中特定的信息,这个信息并不能适用于其他的数据库,例如Oracle。但是后面的字符串仅仅是一个别名。

However, the friendly name could still cause problems because it refers to a specific connection string within the <connectionStrings> section of the web.config file.

然而,使用别名然会造成一些问题。因为它涉及到了一个处于webconfig文件中的<connectionStrings>节点中特定的连接字符串。

In our example, it refers to the connection string used to access Microsoft SQL Server.在我们的例子中,它涉及到了一个访问MS SQL Server的连接字符串。

This means that the GetSubscribers method (the data access code) has to be modified to use a different friendly name to access a different data store such as Oracle.

这意味着GetSubscribers 方法必须被修改,使用不同的别名来访问一个不同的数据库,例如Oracle

To avoid modifying the data access code, we can move the friendly name from the data access code to the <appSettings> section of the web.config file and have the data access code dynamically extract it in runtime as follows:

 为了避免修改GetSubscribers 方法,我们可以将别名从data access code中移动到web.config文件的<appSettings>节点中,并在运行时按照如下方式动态地提取数据访问代码
 
string connectionStringName = ConfigurationSettings.AppSettings["ConnectionStringName"];

We also move the provider name to the <appSettings> section:  我们同样需要将ProviderName移动到<appSettings>节点中

string providerName = ConfigurationSettings.AppSettings["ProviderName"];

Page developers simply change the value attribute of the <add> subelement of the <appSettings> element to the same data access code to access a different data store without making any changes in the data access code itself.

页面开发者仅仅需要简单地修改add子元素的属性值以及appSettings元素的属性值,然后相同的数据访问代码就可以访问不同的数据库。好处是,不需要在data access code中作出任何改变。

======================================================================================================================================

Figure 5 presents the version of the data access code (the GetSubscribers method) that contains the recent changes.

展示GetSubscribers 方法最近的改变

Figure 5. The version of the GetSubscribers method to extract the provider name and the friendly name of the connection string from the web.config file

 GetSubscribers 方法从webconfig文件中提取providername以及连接字符串的别名
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); //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;
}

Data Source Controls   数据源控件

The latest version of the GetSubscribers method as shown in Figure 5 is still not generic because of the following issues:

GetSubscribers 的最新版本如 Figure 5所示,但仍然不是通用的:原因如下

  • 1.The method contains data-store—specific information, i.e., the command text and command type. Therefore, page developers still have to modify the method before they can use it to access a different database.

方法仍然包含了data-store—specific的信息,命令文本以及命令类型。因此页面开发者在访问一个不同的数据库的之前,仍然需要修改GetSubscribers 方法。

  • 2.The method returns an instance of the DataView class to its callers so that the method feeds its callers tabular data.

方法返回了一个DataView 类的实例给它的调用者,所以这个方法能够满足调用者要求的表格数据

We can think of this as a contract between the GetSubscribers method and its callers.

我们可以把这个看做GetSubscribers 方法和它的调用者之间的一个约定。

The callers expect the GetSubscribers method to honor the contract under all circumstances even when the underlying data store itself is not tabular.

调用者期待GetSubscribers 方法在所有的情况下都能"守信",即便底层数据并没有按照表格进行存储。

Since the GetSubscribers method uses ADO.NET objects to access the underlying data store, it cannot access a hierarchical data store, such as an XML file, where instances of the classes in the System.Xml and its sub                 namespaces must be used instead of ADO.NET objects.

由于GetSubscribers 方法使用ADO.NET对象访问底层数据存储,它无法访问分层数据存储,例如xml文件,必须使用的类在System.Xml 命名空间以及子命名空间下,而非ADO.NET对象。

The main problem with the data access code used in the GetSubscribers method is that it directly contains the actual code that extracts the data from the underlying data store.

GetSubscribers 方法中进行数据访问的代码的主要问题是:它直接包含了从底层数据存储提取数据的实际代码。

This is exactly the kind of problem that the .NET Framework 2.0 provider pattern is specifically designed to solve.

.net2.0中提供者模式正是为了解决这种问题而被设计的。

According to the provider pattern, the GetSubscribers method must delegate the responsibility of providing the code for accessing the data store to a different class.

根据提供者模式,GetSubscribers 必须将访问数据存储的的代码职责分配到不同的类中。

It is called the code provider class. The type of code provider class depends on the type of the data store it accesses.

这个类被称为代码提供者类,代码提供者类取决它所要访问的数据存储的类型。

These code provider classes are collectively known as data source controls.  ASP.NET 2.0 comes with several different types of data source controls

这些代码提供者被统称为数据源控件,ASP.NET 2.0有几种不同类型的数据源控件。

including SqlDataSourceAccessDataSourceObjectDataSourceXmlDataSource, and SiteMapDataSource controls.

包括SqlDataSource,AccessDataSource,ObjectDataSource,XmlDataSource和SiteMapDataSource控件。

The SqlDataSource control is specifically designed to update, delete, insert, and extract data from relational data stores such as Microsoft SQL Server and Oracle.

SqlDataSource 被设计用来更新,删除,插入,并从相关的数据存储提取数据,比如SQL Server和Oracle。

The AccessDataSource control is a subclass of the SqlDataSource control that knows how to work with Microsoft Access databases.

AccessDataSource是SqlDataSource的子类,能够用来处理Access数据库

The ObjectDataSource control, on the other hand, uses in-memory business objects as its data store.

ObjectDataSource ,另一方面,在内存中存储业务数据作为它的数据存储

The XmlDataSource control is specifically designed to extract data from XML documents. However, the XmlDataSource control does not provide write access to the underlying XML document.

XmlDataSource用来从xml文档中提取数据。然而,XmlDataSource并不提供对xml文件的写操作权限。

Each data source control exposes one or more views of its underlying data store. Each view is an instance of an appropriate class.

For instance, the SqlDataSource, AccessDataSource, and ObjectDataSource controls expose views that are instances of SqlDataSourceViewAccessDataSourceView, and ObjectDataSourceView classes, respectively.

Views hide the real type of the underlying data store and make it act like the type that the data access code expects.

For instance, the GetSubscribers method expects a tabular type of data store because it feeds its clients tabular data.

The tabular views allow the GetSubscribers method to extract tabular data from the underlying data store even when the data store itself is a hierarchical data source, such as an XML document.

This allows the GetSubscribers method to treat both tabular and hierarchical data stores as tabular data stores.

Data source controls can provide their clients with two types of views: tabular and hierarchical.

ASP.NET 2.0 comes with two data source controls that provide both types of views, XmlDataSource and SiteMapDataSource.

The rest of the data source controls—SqlDataSource, AccessDataSource, and ObjectDataSource—only present tabular views.

However, they can be extended to provide both tabular and hierarchical views.

抽象工厂在ADO.Net中的应用的更多相关文章

  1. 设计模式(四)抽象工厂模式(Abstract Factory Pattern)

    一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码,而工厂方法模式每个具体工厂类只完成单个实例的创建 ...

  2. 深入浅出设计模式——抽象工厂模式(Abstract Factory)

    模式动机在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法.但是有时候我们需要一个工厂可 ...

  3. C#设计模式(4)——抽象工厂模式

    一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法模式每个具体工厂类只完成单个实例的创 ...

  4. iOS 抽象工厂模式

    iOS 抽象工厂模式 什么是抽象工厂模式 简单了解一下 按照惯例,我们先了解一下什么是抽象工厂模式.抽象工厂模式和工厂方法模式很相似,但是抽象工厂模式将抽象发挥的更加极致,是三种工厂模式中最抽象的一种 ...

  5. C#设计模式——抽象工厂模式(原文转自:http://blog.jobbole.com/78059/)

    一.引言 在上一专题中介绍了工厂方法模式,工厂方法模式是为了克服简单工厂模式的缺点而设计出来的,简单工厂模式的工厂类随着产品类的增加需要增加额外的代码),而工厂方法模式每个具体工厂类只完成单个实例的创 ...

  6. [设计模式]<<设计模式之禅>>抽象工厂模式

    1 女娲的失误 上一篇讲了女娲造人的故事.人是造出来了,世界也热闹了,可是低头一看,都是清一色的类型,缺少关爱.仇恨.喜怒哀乐等情绪,人类的生命太平淡了,女娲一想,猛然一拍 脑袋,忘记给人类定义性别了 ...

  7. 工厂模式在JS中的实践

    .mytitle { background: #2B6695; color: white; font-family: "微软雅黑", "宋体", "黑 ...

  8. 简单工厂模式,工厂方法模式,抽象工厂模式,spring的狂想

    菜鸟D在项目中遇见一个比较纠结的高耦合,所以就想办法来解耦.情况是这样的:系统通过用户选择treeview控件的节点判断调用不同的处理,这些处理中某些东西又是类似的.同事的建议是采用简单工厂,耦合就耦 ...

  9. 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...

随机推荐

  1. ASP.NET MVC 学习第三天

    今天来简单说一下Razor视图引擎语法相关的和视图类. 添加一个MvcTest项目,继续添加一个Home控制器,完成index的视图添加.我们就在index这里分析razor视图引擎.下面是home控 ...

  2. final ,override关键字

    final 有时我们会定义这样一种类,我们不希望其他类继承它,或者不想考虑它是否适合作为一个基类.为了实现这一目的,c++ 11新标准提供了一种防止继承发生的方法,即在类名后跟一个关键字final: ...

  3. 【转】获取android设备 id

    关于本文档 Android的开发者在一些特定情况下都需要知道手机中的唯一设备ID.例如,跟踪应用程序的安装,生成用于复制保护的DRM时需要使用设备的唯一ID.在本文档结尾处提供了作为参考的示例代码片段 ...

  4. php发送get、post请求的几种方法

    方法1: 用file_get_contents 以get方式获取内容 <?php $url='http://www.domain.com/'; $html = file_get_contents ...

  5. 解决在ubuntu下requests 无法找到模块packages

    我明明用pip install requests安装成功了,但是依然报下面的错 错误1 requests.packages.urllib3.disable_warnings()AttributeErr ...

  6. Java7 新特性 switch 可以使用String

    今天和大家分享下 在java7中可以使用String 作为switch 中的参数. 原来在java7之前,switch只能去接收一个 byte.char.short.int 类型 现在在java7中 ...

  7. 【DP】BZOJ 1260: [CQOI2007]涂色paint

    1260: [CQOI2007]涂色paint Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 893  Solved: 540[Submit][Stat ...

  8. [转载]C# winform登陆框验证码的实现

    验证码技术已愈来愈成熟,从最初的数字.字母.字符.汉字已经到目前的语言,其应用也甚广,之前大多数只有在网站上可以看到,现在在一些客户端软件也经常可见(比如证券相关软件).之前做的一个基于 C# 客户端 ...

  9. 使用异步 I/O 大大提高应用程序的性能

    使用异步 I/O 大大提高应用程序的性能 学习何时以及如何使用 POSIX AIO API Linux® 中最常用的输入/输出(I/O)模型是同步 I/O.在这个模型中,当请求发出之后,应用程序就会阻 ...

  10. Codeforces400D Dima and Bacteria

    题意:给你一个无向有权的图,图上的点被分成了几类,对于同类的点你需要判断它们之间相互的最短距离是不是0.满足这个条件之后要输出的是类与类之间的最短距离的矩阵.点给到10^5这么多,判断同类的点显然不能 ...