用设计模式开发通用数据库访问器 (http://dev.poptool.net/wangluo/asp.net/shujuku/11763.html)

2019-03-02 23:42|来源: 网路

(http://www.uml.org.cn/sjms/200510314.htm)
      我们都希望在开发软件的时候能少写一些代码,希望能到处使用,希望不用管什么样的数据库软件都能用,我们该怎么办呢?

我们操作数据库时用到些什么类
       一般来说,我们对数据库进行操作时都会用到一些类,下面我就对着些类做个总结:
1.  SQLServer:
a)         System.Data.SqlClient.SqlDataAdapter:SQL数据适配器。表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接。无法继承此类。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
b)        System.Data.SqlClient.SqlConnection:SQL数据库连接。表示 SQL Server 数据库的一个打开的连接。无法继承此类。
c)        System.Data.SqlClient.SqlCommandBuilder:SQL数据库命令生成器。自动生成具有以下用途的单表命令:使对 DataSet 所做的更改与关联的 SQL Server 数据库相协调。无法继承此类。采用Builder模式设计。
另外还有一些,但是在本文中将用不到,所以这里也就不再叙述了。
2.  Oracle:
a)         System.Data.OracleClient.OracleDataAdapter:Oracle数据适配器。表示用于填充 DataSet 和更新Oracle数据库的一组数据命令和到数据库的连接。无法继承此类。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
b)        System.Data.OracleClient.OracleConnection:Oracle数据库连接。表示一个到Oracle数据库的打开的连接。无法继承此类。
c)        System.Data.OracleClient.OracleCommandBuilder:Oracle数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的Oracle数据库的单表命令。无法继承此类。采用Builder模式设计。
3.  Odbc:
a)         System.Data.Odbc.OdbcDataAdapter:Odbc类型数据数据适配器。表示数据命令集和到Odbc数据源的连接,它们用于填充 DataSet 以及更新该数据源。无法继承此类。。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
b)        System.Data.Odbc.OdbcConnection:Odbc数据库连接。表示到Odbc数据源的连接是打开的。
c)        System.Data.Odbc.OdbcCommandBuilder:Odbc数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的Odbc类型数据源的单表命令。无法继承此类。采用Builder模式设计。
4.  OleDb:
a)         System.Data.OleDb.OleDbDataAdapter:Odbc类型数据数据适配器。表示数据命令集和到OleDb数据源的连接,它们用于填充 DataSet 以及更新该数据源。无法继承此类。。该类继承于System.Data.Common.DbDataAdapter和实现接口System.Data.IDbDataAdapter。采用Adapter模式设计。
b)        System.Data.OleDb.OleDbConnection:OleDb数据库连接。表示到OleDb数据源的连接是打开的。
c)        System.Data.OleDb.OleDbCommandBuilder:OleDb数据库命令生成器。自动生成用于协调 DataSet 的更改与关联的OleDb类型数据源的单表命令。无法继承此类。采用Builder模式设计。
我们需要什么样的数据操作器
       当然是越简单越好了,功能倒不一定要强大,够用就行。希望能支持多种数据库,使用这个操作器的程序不用再考虑是那种数据库;希望能对多个数据库操作,一个项目使用多个数据库却不对增加编程复杂度;希望支持事务,失败能够自动回滚。功能嘛,能读取数据、更新数据就可以了。
通用数据操作器的思路
       对数据库的操作其实就是两件事:出和进。出呢就是从数据库中读取数据,进就是将数据写回数据库,包括新增数据、更新数据、删除数据。
       那么对这两个件事情该怎么做呢?
读取数据时,我们是打开一个连接,实例化一个数据适配器然后填充数据集,关闭连接,即可。这里要注意的是,由于数据集里的表经常是数据库里多个数据表join的结果,所以你甭想让操作器自动生成查询语句,得你自己写。
写入数据的时候,就会有一些麻烦,但因为都是执行单表操作所以你可以不用自己写SQL语句,让操作器自己生成好了。
那么一步步怎么做呢?先打开一个数据库连接,再生成一个查询字符串,接着这两个东东实例化一个数据适配器,在生成一个CommandBuilder的实例并注册为DataAdapter的侦听器,接着配置事务。然后更新数据库,最后关闭连接。事务不能更早配置,是因为配置的事务之后便不允许数据适配器的命令为空。
思路有了,后面就很简单了,我们只需要为每一种数据库连接定义这些操作,然后根据实际情况调用就可以了。
当然我们不希望使用哪种数据库的由调用它的系统作为参数传入,定义在配置文件中似乎更好一些。
由于可能有多个数据库,所以我们应当体现这种情况。比如我们可以定义默认数据库连接为“DBCon”,数据库A的连接为“ADBCon”。
由于要实现多张表的操作,所以我们要定义一个数据集表和表名的映射。
代码实现
       首先定义一个枚举,以指定可以支持哪些数据库:
/// <summary>
     /// 数据库类型枚举
     /// </summary>
     public enum DBType
     {
         /// <summary>
         /// SQLServer
         /// </summary>
         SQLServer,
         /// <summary>
         /// Oracle
         /// </summary>
         Oracle,
         /// <summary>
         /// OleDB
         /// </summary>
         OleDb,
         /// <summary>
         /// Odbc
         /// </summary>
         Odbc
     }
 
     定义一个类来扩展DataTable:
     /// <summary>
     /// 用于更新数据库的数据表、库表名对
     /// </summary>
     public class DataTableExtend
     {
         /// <summary>
         /// 数据表
         /// </summary>
         public System.Data.DataTable dataTable;
 
         /// <summary>
         /// 数据表映射到数据库的表名
         /// </summary>
         public string dataTableName;
 
         /// <summary>
         /// 用于更新数据库的数据表、库表名对构造函数
         /// </summary>
         /// <param name="myTable">用于更新数据库的数据表</param>
         /// <param name="myTableName">数据表映射到数据库的表名</param>
         public DataTableExtend(System.Data.DataTable myTable, string myTableName)
         {
              dataTable = myTable;
              dataTableName = myTableName;
         }
     }
 
     然后写一个类来读取配置文件并获取数据库连接字符串:
     /// <summary>
     /// DBSetting 的摘要说明。
     /// </summary>
     public class DBSetting
     {
         /// <summary>
         /// 数据库连接字符串后缀
         /// </summary>
         public static string DBConnectionEnds
         {
              get
              {
                   return "DBCon";
              }
         }
 
         /// <summary>
         /// 数据库类型后缀
         /// </summary>
         public static string DBTypeEnds
         {
              get
              {
                   return "DBType";
              }
         }
/// <summary>
         /// 获取指定数据库的类型
         /// </summary>
         /// <param name="dbName">指定的数据库名</param>
         /// <returns>指定数据库的类型</returns>
         public static DBType GetDBType(string dbName)
         {
              string dbType = null;
              dbType = AppConfig.GetAppSetting(dbName + DBTypeEnds);
              if (dbType.ToLower() == DBType.Oracle.ToString().ToLower())
              {
                   return DBType.Oracle;
              }
              if (dbType.ToLower() == DBType.Odbc.ToString().ToLower())
              {
                   return DBType.Odbc;
              }
              if (dbType.ToLower() == DBType.OleDb.ToString().ToLower())
              {
                   return DBType.OleDb;
              }
              else
              {
                   return DBType.SQLServer;
              }
         }
/// <summary>
         /// 保存指定数据库的类型
         /// </summary>
         /// <param name="dbType">指定数据库的类型</param>
         /// <param name="dbName">指定的数据库名</param>
         public static void SaveDBType(DBType dbType,string dbName)
         {
              AppConfig.SaveAppSetting(dbName + DBTypeEnds,dbType.ToString());
         }
/// <summary>
         /// 获取指定数据库的连接字符串
         /// </summary>
         /// <param name="dbName">指定的数据库名</param>
         /// <returns>指定数据库的连接字符串</returns>
         public static string GetDBConnectionString(string dbName)
         {
              return AppConfig.GetAppSetting(dbName + DBConnectionEnds);
         }
 
         /// <summary>
         /// 保存指定数据库的连接字符串
         /// </summary>
         /// <param name="connectionString">连接字符串</param>
         /// <param name="dbName">指定的数据库名</param>
         public static void SaveDBConnectionString(string connectionString, string dbName)
         {
              AppConfig.SaveAppSetting(dbName + DBConnectionEnds,connectionString);
         }
}
 
接着为每一种数据库写一个类来执行针对该数据库的操作,例如针对SQL Server:
/// <summary>
     /// 用于SQL数据源操作的类
     /// </summary>
     public class SQLExec
     {
         /// <summary>
         /// 获取数据库连接,读取由Storm.AppSetting的配置文件中dbName + "DBCon"的设置(如针对数据库Test的配置键是“TestDBCon”),若没有,则抛出异常
         /// </summary>
         /// <param name="dbName">要获取数据连接的数据库名</param>
         /// <returns>得到的数据库连接</returns>
         public static SqlConnection GetDBConnection(string dbName)
         {
              return new SqlConnection(DBSetting.GetDBConnectionString());
         }
 
private void ModifyDataBase(DataTableExtend[] dts, string dbName)
         {
              //打开连接
              SqlConnection sqlCon = GetDBConnection(dbName);
              sqlCon.Open();
              //根据数据表的多少生成多个数据适配器并分别生成SQL语句
              int length = dts.Length;
              SqlDataAdapter[] myDataAdapters = new SqlDataAdapter[length];
              for (int i = 0; i < length; i++)
              {
                   string selectText = GetSelectCommand(dts[i].dataTableName);
                   myDataAdapters[i] = new SqlDataAdapter(selectText, sqlCon);
                   SqlCommandBuilder cb = new SqlCommandBuilder(myDataAdapters[i]);
                   myDataAdapters[i].InsertCommand = cb.GetInsertCommand();
                   myDataAdapters[i].UpdateCommand = cb.GetUpdateCommand();
                   myDataAdapters[i].DeleteCommand = cb.GetDeleteCommand();
              }
              //配置事务
              SqlTransaction myTrans;
              myTrans = sqlCon.BeginTransaction(IsolationLevel.RepeatableRead);
              try
              {
                   for (int i = 0; i < length; i++)
                   {
                       myDataAdapters[i].SelectCommand.Transaction = myTrans;
                       myDataAdapters[i].InsertCommand.Transaction = myTrans;
                       myDataAdapters[i].UpdateCommand.Transaction = myTrans;
                       myDataAdapters[i].DeleteCommand.Transaction = myTrans;
                       //更新数据库
                       myDataAdapters[i].Update(dts[i].dataTable);
                   }
                   myTrans.Commit();
                   sqlCon.Close();
                   for(int i = 0; i < length ; i++)
                   {
                       dts[i].dataTable.AcceptChanges();
                   }
              }
              //如果失败,则自动回滚
              catch(Exception ee)
              {
                   myTrans.Rollback();
                   sqlCon.Close();
                   for(int i = 0; i < length ; i++)
                   {
                       dts[i].dataTable.RejectChanges();
                   }
                   throw ee;
              }
         }
    
/// <summary>
         /// 从数据库中读取数据
         /// </summary>
         /// <param name="dt">要承载数据的数据表</param>
         /// <param name="selectString">查询语句</param>
         public void GetData(DataTable dt, string selectString, string dbName)
         {
SqlDataAdapter myDataAdapter = new SqlDataAdapter(selectString,SQLConfig.GetDBConnection(dbName));
              myDataAdapter.Fill(dt);
         }
        
         //自动生成查询语句
private static string GetSelectCommand(string dataTableName)
         {
              string strGet = "SELECT * FROM " +dataTableName;
              return strGet;
         }
}
 
然后就是写一个类来根据实际情况调用这些东东了:
public class DatabaseExecute
     {
         private string dbName;
         /// <summary>
         /// 目标数据库
         /// </summary>
         public string DBName
         {
              get{ return dbName; }
              set{ dbName = value; }
         }
    
         /// <summary>
         /// 生成DatabaseExecute的实例
         /// </summary>
         public DatabaseExecute()
         {
              dbName = null;
         }
 
         /// <summary>
         /// 用指定的目标数据库生成DatabaseModifier的实例
         /// </summary>
         /// <param name="dbName"></param>
         public DatabaseExecute(string dbName)
         {
              this.dbName = dbName;
         }
         /// <summary>
         /// 从数据库中读取数据
         /// </summary>
         /// <param name="dt">要承载数据的数据表</param>
         /// <param name="selectString">查询语句</param>
         public void GetData(DataTable dt, string selectString)
         {
              //操作指定数据库
              if (DBName != null)
              {
                   if (DBSetting.GetDBType(dbName) == DBType.SQLServer)
                   {
                       SQLExec mySQLExec = new SQLExec();
                       mySQLExec. GetData(dt, selectString, DBName);
                   }
                   else if (DBSetting.GetDBType(dbName) == DBType.Odbc)
                   {
                       OdbcExec myOdbcExec = new OdbcExec();
                       myOdbcExec. GetData(dt, selectString, DBName);
                   }
                   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                   {
                       OleDbExec myOleDbExec = new OleDbExec();
                       mySQLExec. GetData(dt, selectString, DBName);
                   }
                   else
                   {
                       OracleExec myOracleExec = new OracleExec();
                       myOracleExec. GetData(dt, selectString, DBName);
                   }
              }
              //操作默认数据库
              else
              {
                   if (DBSetting.GetDBType(“”) == DBType.SQLServer)
                   {
                       SQLExec mySQLExec = new SQLExec();
                       mySQLExec. GetData(dt, selectString, “”);
                   }
                   else if (DBSetting.GetDBType(“”) == DBType.Odbc)
                   {
                       OdbcExec myOdbcExec = new OdbcExec();
                       myOdbcExec. GetData(dt, selectString, “”);
                   }
                   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                   {
                       OleDbExec myOleDbExec = new OleDbExec();
                       mySQLExec. GetData(dt, selectString, “”);
                   }
                   else
                   {
                       OracleExec myOracleExec = new OracleExec();
                       myOracleExec. GetData(dt, selectString, “”);
                   }
              }
         }
 
         /// <summary>
         /// 根据数据表组更新数据库
         /// </summary>
         /// <param name="dts">要更新的数据表组</param>
         public void ModifyDataBase(DataTableExtend[] dts)
         {
              //操作指定数据库
              if (dbName != null)
              {
                   if (DBSetting.GetDBType(dbName) == DBType.SQLServer)
                   {
                       SQLExec mySQLExec = new SQLExec();
                       mySQLExec ModifyDataBase(dts,dbName);
                   }
                   else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)
                   {
                       OdbcExec mySQLExec = new OdbcExec();
                       myOdbcExec ModifyDataBase(dts,dbName);
                   }
                   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                   {
                       OleDbExec mySQLExec = new OleDbExec();
                       myOleDbExec ModifyDataBase(dts,dbName);
                   }
                   else
                   {
                       OracleExec mySQLExec = new OracleExec();
                       myOracleExec ModifyDataBase(dts,dbName);
                   }
              }
              //操作默认数据库
              else
              {
                   if (DBSetting.GetDBType(“”) == DBType.SQLServer)
                   {
                        SQLExec mySQLExec = new SQLExec();
                       mySQLExec ModifyDataBase(dts, “”);
                   }
                   else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)
                   {
                       OdbcExec mySQLExec = new OdbcExec();
                       myOdbcExec ModifyDataBase(dts, “”);
                   }
                   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)
                   {
                       OleDbExec mySQLExec = new OleDbExec();
                       myOleDbExec ModifyDataBase(dts, “”);
                   }
                   else
                   {
                       OracleExec mySQLExec = new OracleExec();
                       myOracleExec ModifyDataBase(dts, “”);
                   }
              }
}
 
这样,在项目中只要引用这个DatabaseExecute类就可以了。
最后,要注意的几点:
1.              对于多表操作而言,因为表间有关联,所以操作的顺序很重要,本构件操作的顺序是从数据表数组的前向后处理,请千万注意表处理的顺序!
2.              默认数据库连接由配置文件中“DBCon”的设置决定,非默认数据库连接由配置文件中“*DBCon”的设置决定,其中星号代表数据库标识
3.              默认数据库类型由配置文件中“DBCon”的设置决定,非默认数据库类型由配置文件中“*DBCon”的设置决定,其中星号代表数据库标识
4.              针对每一个数据库都有两个配置,分别是数据库连接和数据库类型。


转自:http://www.cnblogs.com/snowball/archive/2006/07/06/444708

相关问答

更多
  • 这是一个需要考虑的建筑设计: 视图和控制器位于MVC网站中 。 模型在一个单独的项目中。 数据访问代码位于名为DataAccess或Repository的第三个项目中。 该网站引用了Models和DataAccess项目。 DataAccess项目还引用了Models项目。 这样,数据访问代码是分开的。 它更容易找到和维护。 它可以用于另一种解决方案。 您甚至可以将其换成完全不同的数据访问层 - 例如,从Linq切换到SQL到Entity Framework或经典的ADO.Net。 通过将模型保存在单独的项 ...
  • 邮件模板没什么复杂的,可能人家不高兴写。html模板,简单点例如:
    {content}
    将邮件的内容(本身就是一长串html),替换到{content}的位置,就可以了,类似的,你可以放置多个占位符,用来替换不同的邮件内容。
  • 在数据库实现上实现一个抽象层,以便您的应用程序调用GetUser()和UpdateWidget()而不是IDbCommand.ExecuteReader()和朋友。 这些方法将存在于接口上,每个实体类型一个。 IUserRepository IWidgetRepository 每个数据库平台应该有一个每个接口的实现者。 MySqlUserRepository MySqlWidgetRepository MimerUserRepository MimerWidgetRepository 然后创建一个工厂 ...
  • 想到一些想法。 所有的信息是否需要在同一页上? 如果你可以将内容分成多页,我建议你从那里开始。 假设你需要将所有内容保存在一个页面上,我同意rick关于延迟加载的方法。 您的HTML输出将只是一个DIV,并且一些jQuery可以通过AJAX下载并填充内容。 当用户点击以查看隐藏的内容时,您可能会下载该内容,或者只是在页面加载时在后台下载隐藏的内容。 无论哪种方式都会提高性能。 将内容存储在数据库中而不是单独的HTML文件的决定与性能问题是分开的。 数据库可能不会成为你的瓶颈,但当然,我只是猜测在这里不太了解 ...
  • 目前尚不清楚您使用的是哪种项目类型 - ASP.NET webforms或ASP.NET MVC。 问题是标记为MVC,但您指的是代码隐藏。 在webforms和显示来自数据库的数据方面,它的一大优势是它的服务器控件集。 它们有助于摆脱“循环遍历数组/数据集并写出HTML标记”的思维方式。 与编写循环代码相比,您将在相同的时间内完成更多工作。 ASP.NET webforms提供数据绑定到常用控件 - 下拉列表,网格等。 如果您的目标是ASP.NET网络表单 ,请考虑本文及其示例代码 ,以便开始使用数据绑定 ...
  • 物理数据层可能与EF / NHib / likes通常使用的实体模型不同(通常是)。 但是,无论何时将数据模型抽象为代码,都会改变某些部分。 这些适应与您的OR / M的灵活性有关。 更灵活的是它会有更少的适应性。 Physical data layer may be different (and usually is) from the entity model that's usually used by EF/NHib/likes. But whenever you do any kind of ab ...
  • 编写你自己的模板系统基本上是在ASP.NET中重新发明轮子 。 我不会推荐它,除非你打算更多地了解车轮(在这种情况下,我会说去做)。 一个更好的选择是使用微软提供的作为框架一部分的主页 。 微软已经想出了实现模板系统的硬件细节,甚至可以让你在模板中嵌套模板。 如果你想要不同的外观,你可以动态地交换模板。 对于一个CMS,我会说你最好使用母版页而不是创建自己的页面。 Writing your own template system is basically reinventing the wheel in A ...
  • 首先,Hadoop不是数据库。 它是FS(HDFS)+计算框架。 如果您正在寻找在Hadoop之上运行的可扩展数据库工具,您可能会发现HBase非常适合。 如果您知道,MS也有自己的Hadoop产品HDInsights 。 通过HDInsights,您可以在Windows机器上方便地使用HBase。 如果您需要有关如何配置HDInsights的帮助,可以查看此链接 。 你也可以在他们的网站上找到一些例子。 它们还提供了Hadoop .NET sdk,使得从.NET使用Hadoop变得更容易。 看看这个 。 ...
  • 做吧 我现在也这样做。 但是,SQL 2000不受支持。 即便是我现在所坐的银行现在正在用2005/2008取代它。我会认真考虑升级。 Web应用程序? 使用SPLA(仅对服务提供商提供合法许可 - 此处购买的许可证不合法),无论如何都可以获得2008R2和SQL 2008 R2。 Do it. I do the same at the moment. SQL 2000, though - is out of support. Even the bank I am sitting in at the mom ...
  • 只需将上下文设为通用 将通用存储库更改为例如: public class GenericRepository where TContext : DbContext where TEntity : class { internal TContext context; internal DbSet dbSet; public GenericRepositor ...