zoukankan      html  css  js  c++  java
  • 适用于关系型数据库的抽象工厂的数据库访问类

    适用于SQLite、Access、MySQL、MSSQLServer、Oracle这类关系型数据库,不适于非关系型数据库,例如MongoDB。

    下面是代码:

      1 using System;
      2 using System.Configuration;
      3 using System.Data;
      4 using System.Data.Common;
      5 using System.Data.SQLite;
      6 
      7 namespace WinFormTest
      8 {
      9     public static class DbHelperSQL
     10     {
     11         private static readonly object Obj4Lock = new object();
     12         private static readonly string ConnectionString = ConfigurationManager.
     13             ConnectionStrings["ConnectionString"].ConnectionString;
     14 
     15         /// <summary>
     16         ///  程序每次运行都只创建一个工厂
     17         /// </summary>
     18         private static DbProviderFactory DBProviderFactory
     19         {
     20             get
     21             {
     22                 var providerFactoryString = ConfigurationManager.ConnectionStrings["ConnectionString"].ProviderName;
     23                 if (providerFactoryString == "System.Data.SQLite")
     24                 {
     25                     return SQLiteFactory.Instance;
     26                 }
     27 
     28                 var dbProviderFactory = DbProviderFactories.GetFactory(providerFactoryString);
     29                 if (dbProviderFactory == null)
     30                 {
     31                     throw new Exception("dbProviderFactory==null");
     32                 }
     33 
     34                 return dbProviderFactory;
     35             }
     36         }
     37 
     38 
     39         public static int ExecuteNonQuery(string commandText, bool isStoredProcedure)
     40         {
     41             if (commandText == null)
     42             {
     43                 throw new ArgumentNullException("commandText");
     44             }
     45 
     46             int result;
     47 
     48             lock (Obj4Lock)
     49             {
     50                 using (var connection = CreateConnection())
     51                 {
     52                     using (var transaction = CreateTransaction(connection))
     53                     {
     54                         using (var command = CreateCommand(commandText, isStoredProcedure, connection, transaction))
     55                         {
     56                             try
     57                             {
     58                                 result = command.ExecuteNonQuery();
     59                                 command.Parameters.Clear();
     60                                 transaction.Commit();
     61                             }
     62                             catch
     63                             {
     64                                 transaction.Rollback();
     65                                 return 0;
     66                             }
     67                         }
     68                     }
     69                 }
     70             }
     71 
     72             return result;
     73         }
     74 
     75         public static object ExecuteScalar(string commandText, bool isStoredProcedure)
     76         {
     77             if (commandText == null)
     78             {
     79                 throw new ArgumentNullException("commandText");
     80             }
     81 
     82             object result;
     83 
     84             lock (Obj4Lock)
     85             {
     86                 using (var connection = CreateConnection())
     87                 {
     88                     using (var transaction = CreateTransaction(connection))
     89                     {
     90                         using (var command = CreateCommand(commandText, isStoredProcedure, connection, transaction))
     91                         {
     92                             try
     93                             {
     94                                 result = command.ExecuteScalar();
     95                                 command.Parameters.Clear();
     96                                 transaction.Commit();
     97                             }
     98                             catch
     99                             {
    100                                 transaction.Rollback();
    101                                 return null;
    102                             }
    103                         }
    104                     }
    105                 }
    106             }
    107 
    108             return result;
    109         }
    110 
    111         public static IDataReader ExecuteReader(string commandText, bool isStoredProcedure)
    112         {
    113             if (commandText == null)
    114             {
    115                 throw new ArgumentNullException("commandText");
    116             }
    117 
    118             lock (Obj4Lock)
    119             {
    120                 var connection = CreateConnection();
    121 
    122                 var command = CreateCommand(commandText, isStoredProcedure, connection, null);
    123 
    124                 try
    125                 {
    126                     var myReader = command.ExecuteReader(CommandBehavior.CloseConnection);
    127                     command.Parameters.Clear();
    128                     return myReader;
    129                 }
    130                 catch
    131                 {
    132                     connection.Close();
    133                     throw;
    134                 }
    135             }
    136         }
    137 
    138         public static DataSet Query(string commandText, bool isStoredProcedure)
    139         {
    140             if (commandText == null)
    141             {
    142                 throw new ArgumentNullException("commandText");
    143             }
    144 
    145             var dataSet = new DataSet();
    146 
    147             lock (Obj4Lock)
    148             {
    149                 using (var connection = CreateConnection())
    150                 {
    151                     using (var transaction = CreateTransaction(connection))
    152                     {
    153                         using (var command = CreateCommand(commandText, isStoredProcedure, connection, transaction))
    154                         {
    155                             using (var dataAdapter = DBProviderFactory.CreateDataAdapter())
    156                             {
    157                                 if (dataAdapter == null)
    158                                 {
    159                                     throw new ArgumentNullException("commandText");
    160                                 }
    161 
    162                                 try
    163                                 {
    164                                     dataAdapter.Fill(dataSet, "dataSet");
    165                                     command.Parameters.Clear();
    166                                     transaction.Commit();
    167                                 }
    168                                 catch
    169                                 {
    170                                     transaction.Rollback();
    171                                     return null;
    172                                 }
    173                             }
    174                         }
    175                     }
    176                 }
    177             }
    178 
    179             return dataSet;
    180         }
    181 
    182 
    183         private static IDbConnection CreateConnection()
    184         {
    185             IDbConnection connection = DBProviderFactory.CreateConnection();
    186             if (connection == null)
    187             {
    188                 throw new Exception("connection == null");
    189             }
    190 
    191             connection.ConnectionString = ConnectionString;
    192 
    193             if (connection.State != ConnectionState.Open)
    194             {
    195                 connection.Open();
    196             }
    197 
    198             return connection;
    199         }
    200 
    201         private static IDbTransaction CreateTransaction(IDbConnection connection)
    202         {
    203             var transaction = connection.BeginTransaction();
    204             if (transaction == null)
    205             {
    206                 throw new ArgumentNullException("connection");
    207             }
    208             return transaction;
    209         }
    210 
    211         private static IDbCommand CreateCommand(string commandText, bool isStoredProcedure,
    212             IDbConnection connection, IDbTransaction transaction)
    213         {
    214             IDbCommand command = DBProviderFactory.CreateCommand();
    215             if (command == null)
    216             {
    217                 throw new Exception("command == null");
    218             }
    219 
    220             command.Connection = connection;
    221             command.CommandType = isStoredProcedure ? CommandType.StoredProcedure : CommandType.Text;
    222             command.CommandText = commandText;
    223             command.Transaction = transaction;
    224 
    225             return command;
    226         }
    227     }
    228 }

    解释:

    1、Obj4Lock用于锁定代码块,保证在多线程程序中,只有一个数据库连接存在。

    2、外部接口只有ExecuteNonQuery、ExecuteScalar、ExecuteReader、Query四个方法,可以使用存储过程和事务。

    3、为什么不用参数化查询?一是因为面向接口编程的原因,程序中不能使用具体数据库相关的参数对象,只能使用IDbParameter和DbParameter,这两个是接口和抽象类,不能够实例化,可以写在工厂中,但是没法使用。二是我做的程序中不需要参数化查询。

    4、代码可读性良好,不必注释了。

    下面是配置文件:

    1 <?xml version="1.0" encoding="utf-8" ?>
    2 <configuration>
    3   <connectionStrings>
    4     <!--<add name="ConnectionString" connectionString="Data Source=Test" providerName="System.Data.SQLite"/>-->
    5     <!--<add name="ConnectionString" connectionString="Provider=Microsoft.ACE.OLEDB.12.0; Data Source=TestAccess.accdb" providerName="System.Data.OleDb"/>-->
    6     <add name="ConnectionString" connectionString="server=127.0.0.1;database=testDB;uid=root;pwd=123456" providerName="MySql.Data.MySqlClient"/>
    7   </connectionStrings>
    8 </configuration>

    通过更改配置文件,就可以实现对数据库种类的屏蔽了。

    下面是用了抽象工厂的数据库访问类和普通数据库访问类的效率差异:

    数据库

    类型

    2

    5

    10

    20

    50

    100

    200

    SQLite

    文件

    0.197s

    0.285s

    0.547s

    1.099s

    2.509s

    5.632s

    11.386s

    SQLite(抽象工厂)

    文件

    0.246s

    0.362s

    0.499s

    1.191s

    2.539s

    6.692s

    10.464s

    Access

    文件

    0.199s

    0.280s

    0.521s

    1.071s

    2.604s

    5.320s

    10.760s

    Access(抽象工厂)

    文件

    0.363s

    0.510s

    0.780s

    1.326s

    2.805s

    5.569s

    10.648s

    MySql

    服务器

    0.217s

    0.106s

    0.226s

    0.331s

    0.952s

    1.545s

    2.666s

    MySql(抽象工厂)

    服务器

    0.310s

    0.323s

    0.403s

    0.545s

    0.942s

    1.623s

    2.746s

    表中的数字是线程数,每个线程只执行一条语句。

    All Comments are Welcome.

  • 相关阅读:
    drop table 、delete table和truncate table的区别
    润乾报表 删除导出excel弹出框里的选项
    学习笔记: 委托解析和封装,事件及应用
    学习笔记: 特性Attribute详解,应用封装
    学习笔记: 反射应用、原理,完成扩展,emit动态代码
    学习笔记: 泛型应用、原理、协变逆变、泛型缓存
    jmeter4.x centos7部署笔记
    rabbitmq3.7.5 centos7 集群部署笔记
    rabbitmq3.8.3 centos7 安装笔记
    UVA-12436 Rip Van Winkle's Code (线段树区间更新)
  • 原文地址:https://www.cnblogs.com/yao2yao4/p/2811894.html
Copyright © 2011-2022 走看看