数据库小工具整合版

2019-12-14 09:00栏目:编程
TAG:

3、其他数据库的帮助类,正如以上所说的,只要重写DbHelper类的DbProviderFactory属性并在构造函数为其赋值即可。

bob体育平台 1

以上我们好像没有指定数据库连接字符串,大家如果看下DbHelper的代码,就知道要使用它必须在config中配置两个参数,如下:

DbHelper完整代码如下:

上图显示执行一条 SQL 语句后的结果。

bob体育平台 2        DbHelper db = new DbHelper();
bob体育平台 3        DbCommand cmd = db.GetStoredProcCommond("t2_insert");
bob体育平台 4bob体育平台,        db.AddInParameter(cmd, "@timeticks", DbType.Int64, DateTime.Now.Ticks);
bob体育平台 5        db.AddOutParameter(cmd, "@outString", DbType.String, 20);
bob体育平台 6        db.AddReturnParameter(cmd, "@returnValue", DbType.Int32);
bob体育平台 7
bob体育平台 8        db.ExecuteNonQuery(cmd);
bob体育平台 9
bob体育平台 10 string s = db.GetParameter(cmd, "@outString").Value as string;//out parameter
bob体育平台 11 int r = Convert.ToInt32(db.GetParameter(cmd, "@returnValue").Value);//return value
bob体育平台 12

我们可以看到,在此类中,有很多用于创建数据库相关对象的类型,如DbConnection,DbCommand,DbDataAdapter等。

bob体育app,上图显示出数据库中的表的结构。

3)返回DataSet

而且,实现诸如SqlConnection、SqlCommand、SqlDataAdapter(这里用的是SQL Server)的类型,都分别继承自DbConnection,DbCommand,DbDataAdapter,

第78到85行的 RunQueryTableData 方法使用 DbProviderFactory 类的 CreateDataAdapter 方法创建一个 DbDataAdapter (第80行),然后使用 DbDataAdapter 类的 Fill 方法来填充 DataSet (第83行),最后返回该 DataSet 的 Tables 属性中的第一个 DataTabe 的 DefaultView (第84行)。

 

二、实现基本的DbHelper帮助类

这个程序主要使用 System.Data.Common 命名空间中的类来进行工作 。

bob体育平台 13 <appSettings>
bob体育平台 14 <add key="DbHelperProvider" value="System.Data.SqlClient"/>
bob体育平台 15 <add key="DbHelperConnectionString" value="Data Source=(local);Initial Catalog=DbHelperTest;Persist Security Info=True;User ID=sa;Password=sa"/>
bob体育平台 16 </appSettings>

2、参照以上,实现SQLite帮助类如下:

当时,对各个不同的数据库是分别实现这个“数据库小工具”的。

bob体育平台 17        DbHelper db = new DbHelper();
bob体育平台 18        DbCommand cmd = db.GetStoredProcCommond("t1_insert");
bob体育平台 19        db.AddInParameter(cmd, "@id", DbType.String, "heihei");
bob体育平台 20        db.ExecuteNonQuery(cmd);

4、在DbHelper编写一些用于实现数据库相关操作的方法,这里就用到了DbProviderFactory类中的方法,以下方法仅供参考,具体请参照其他完整的DbHelp帮助类,

  1. 其对应的.NET数据类型。

bob体育平台 21      DbHelper db = new DbHelper();
bob体育平台 22        DbCommand cmd = db.GetStoredProcCommond("t2_insert");
bob体育平台 23        db.AddInParameter(cmd, "@timeticks", DbType.Int64, DateTime.Now.Ticks);
bob体育平台 24        db.AddOutParameter(cmd, "@outString", DbType.String, 20);
bob体育平台 25        db.AddReturnParameter(cmd, "@returnValue", DbType.Int32);
bob体育平台 26
bob体育平台 27 using (DbDataReader reader = db.ExecuteReader(cmd))
bob体育平台 28bob体育平台 29 bob体育平台 30{
bob体育平台 31            dt.Load(reader);
bob体育平台 32        }
bob体育平台 33 string s = db.GetParameter(cmd, "@outString").Value as string;//out parameter
bob体育平台 34 int r = Convert.ToInt32(db.GetParameter(cmd, "@returnValue").Value);//return value
bob体育平台 35

三、实现具体的数据库帮助类

using System;
using System.IO;
using System.Data;
using System.Data.Common;
using System.Windows.Forms;

namespace Skyiv.Ben.DbTools
{
  public partial class MainForm : Form
  {
    public MainForm()
    {
      InitializeComponent();
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
      try
      {
        tbxDsn.Text = "Data Source=:memory:";
        tbxSql.Text = "select sqlite_version()";
        var table = DbProviderFactories.GetFactoryClasses();
        lbxDbProvider.ValueMember = "InvariantName";
        lbxDbProvider.DataSource = table;
        dgvMain.DataSource = table;
        lbxDbProvider.SelectedValue = "System.Data.SQLite";
      }
      catch (Exception ex)
      {
        tbxMessage.AppendText(Pub.GetMessage(ex));
      }
    }

    private void btnSubmit_Click(object sender, EventArgs e)
    {
      btnSubmit.Enabled = false;
      try
      {
        tbxMessage.Clear();
        var factory = DbProviderFactories.GetFactory(lbxDbProvider.SelectedValue.ToString());
        using (var conn = factory.CreateConnection())
        {
          conn.ConnectionString = tbxDsn.Text;
          conn.Open();
          tbxMessage.AppendLine("Client Version: [{0}]", Pub.GetClientVersion(Path.GetFileNameWithoutExtension(factory.ToString())));
          tbxMessage.AppendLine("Server Version: [{0}]", conn.ServerVersion);
          var sql = tbxSql.Text.Trim();
          if (sql.Length != 0)
          {
            var comm = conn.CreateCommand();
            comm.CommandText = sql;
            var isQuery = IsQuery(sql);
            var rows = int.MinValue;
            if (!isQuery) rows = comm.ExecuteNonQuery();
            else if (chkStruct.Checked) dgvMain.DataSource = RunQueryTableStruct(comm);
            else dgvMain.DataSource = RunQueryTableData(factory, comm);
            tbxMessage.AppendText("运行 SQL 语句完毕(" + (!isQuery ? "非查询" : (chkStruct.Checked ? "表结构" : "查询")) + ")");
            if (rows >= 0) tbxMessage.AppendText(",受影响的行数: " + rows.ToString("N0"));
          }
          else tbxMessage.AppendText("完成");
        }
      }
      catch (Exception ex)
      {
        tbxMessage.AppendText(Pub.GetMessage(ex));
      }
      btnSubmit.Enabled = true;
    }

    DataView RunQueryTableStruct(DbCommand comm)
    {
      using (var r = comm.ExecuteReader(CommandBehavior.KeyInfo))
      {
        return r.GetSchemaTable().DefaultView;
      }
    }

    DataView RunQueryTableData(DbProviderFactory factory, DbCommand comm)
    {
      var da = factory.CreateDataAdapter();
      da.SelectCommand = comm;
      var ds = new DataSet();
      da.Fill(ds);
      return ds.Tables[0].DefaultView;
    }

    bool IsQuery(string sql)
    {
      return sql.ToUpper().StartsWith("SELECT");
    }
  }
}

5)输入参数/输出参数/返回值的使用(比较重要哦)

一、在System.Data.Common命名空间下,存在这样的一个类:

using System;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace Skyiv.Ben.DbTools
{
  static class Pub
  {
    public static string GetMessage(Exception ex)
    {
      var sb = new StringBuilder();
      for (sb.Append("错误: "); ex != null; ex = ex.InnerException)
      {
        sb.AppendFormat("[{0}]: ", ex.GetType());
        sb.AppendLine(ex.Message);
      }
      return sb.ToString();
    }

    public static void AppendLine(this TextBoxBase tbx, string fmt, params object[] args)
    {
      tbx.AppendText(string.Format(fmt, args) + Environment.NewLine);
    }

    public static Version GetClientVersion(string name)
    {
      foreach (var a in AppDomain.CurrentDomain.GetAssemblies()) if (name == a.GetName().Name) return a.GetName().Version;
      return null;
    }
  }
}

其实,DbHelper需要的仅仅是两个字符串,你可以自己修改,作成加密什么的...
好了,就这样,DbHelper的代码是非常简单和透明的,只是在ado.net上做了一点小包装,改变了一下使用它的程序员的编码方式,去除掉一些比较" 物理级"的编程概念,如connection的open和close之类的,使程序员更专注于业务逻辑代码的编写,少死掉点脑细胞,另外,统一了数据操作层的数据操作代码的风格和格式,维护起来很方便的撒~~~
另:以上代码大家可以随意使用, 不需要给我版权费的啦,嘿嘿.如果大家发现有什么BUG,或者有更好的数据操作类的实现方式,请联系我哦.

//帮助类的基类(抽象类)
    public abstract class DbHelper
    {
        public DbHelper(string connectionString)
        {
            ConnectionString = connectionString;
        }

        public abstract DbProviderFactory DbProviderFactory {  get; } 

        public string ConnectionString { get; }

        //以下实现的帮助类方法,仅供该例子使用,具体请参照其他完整的DbHelp帮助类
        private void ThrowExceptionIfLengthNotEqual(string[] sqls, params DbParameter[][] parameters)
        {
            if (parameters.GetLength(0) != 0 && sqls.Length != parameters.GetLength(0)) throw new ArgumentException($"一维数组{nameof(sqls)}的长度与二维数组{nameof(parameters)}长度的第一维长度不一致");
        }

        private T[] Execute<T>(string[] sqls, CommandType commandType = CommandType.Text, ExecuteMode executeMode = ExecuteMode.NonQuery, params DbParameter[][] parameters)
        {
            ThrowExceptionIfLengthNotEqual(sqls, parameters);
            if(executeMode == ExecuteMode.NonQuery && typeof(T) != typeof(int)) throw new InvalidCastException("使用NonQuery模式时,必须将类型T指定为int");
            using (DbConnection connection = DbProviderFactory.CreateConnection())
            using (DbCommand command = DbProviderFactory.CreateCommand())
            {
                connection.ConnectionString = ConnectionString;
                connection.Open();
                command.Connection = connection;
                command.CommandType = commandType;
                DbTransaction transaction = connection.BeginTransaction();
                command.Transaction = transaction;
                try
                {
                    List<T> resultList = new List<T>();
                    for (int i = 0; i < sqls.Length; i++)
                    {
                        command.CommandText = sqls[i];
                        if (parameters.GetLength(0) != 0)
                        {
                            command.Parameters.Clear();
                            command.Parameters.AddRange(parameters[i]);
                        }
                        object result = null;
                        switch (executeMode)
                        {
                            case ExecuteMode.NonQuery:
                                result = command.ExecuteNonQuery(); break;
                            case ExecuteMode.Scalar:
                                result = command.ExecuteScalar(); break;
                            default: throw new NotImplementedException();
                        }
                        resultList.Add((T)Convert.ChangeType(result, typeof(T)));
                    }
                    transaction.Commit();
                    return resultList.ToArray();
                }
                catch
                {
                    transaction.Rollback();
                    throw;
                }
            }
        }

        public int ExecuteNonQuery(string sql, params DbParameter[] parameter) => ExecuteNonQuery(new string[] { sql }, new DbParameter[][] { parameter })[0];

        public int[] ExecuteNonQuery(string[] sqls, params DbParameter[][] parameters)=> Execute<int>(sqls, CommandType.Text, ExecuteMode.NonQuery,parameters);

        public int ExecuteNonQueryWithProc(string sql, params DbParameter[] parameter) => ExecuteNonQueryWithProc(new string[] { sql },  new DbParameter[][] { parameter })[0];

        public int[] ExecuteNonQueryWithProc(string[] sqls, params DbParameter[][] parameters) => Execute<int>(sqls, CommandType.StoredProcedure, ExecuteMode.NonQuery, parameters);

        public T ExecuteScalar<T>(string sql, params DbParameter[] parameter) => ExecuteNonQuery<T>(new string[] { sql }, new DbParameter[][] { parameter })[0];

        public T[] ExecuteNonQuery<T>(string[] sqls, params DbParameter[][] parameters) => Execute<T>(sqls, CommandType.Text,ExecuteMode.Scalar, parameters);

        public T ExecuteScalarWithProc<T>(string sql, params DbParameter[] parameter) => ExecuteNonQuery<T>(new string[] { sql }, new DbParameter[][] { parameter })[0];

        public T[] ExecuteNonQueryWithProc<T>(string[] sqls, params DbParameter[][] parameters) => Execute<T>(sqls, CommandType.StoredProcedure, ExecuteMode.Scalar, parameters);

        enum ExecuteMode
        {
            NonQuery,Scalar
        }

        private DataTable[] Fill(string[] selectSqls, CommandType commandType = CommandType.Text, params DbParameter[][] parameters)
        {
            ThrowExceptionIfLengthNotEqual(selectSqls, parameters);
            using (DbConnection connection = DbProviderFactory.CreateConnection())
            using (DbDataAdapter adapter = DbProviderFactory.CreateDataAdapter())
            using (DbCommand command = DbProviderFactory.CreateCommand())
            {
                connection.ConnectionString = ConnectionString;
                connection.Open();
                command.Connection = connection;
                command.CommandType = commandType;
                adapter.SelectCommand = command;
                List<DataTable> resultList = new List<DataTable>();
                for (int i = 0; i < selectSqls.Length; i++)
                {
                    command.CommandText = selectSqls[i];
                    if (parameters.GetLength(0) != 0)
                    {
                        command.Parameters.Clear();
                        command.Parameters.AddRange(parameters[i]);
                    }
                    DataTable table = new DataTable();
                    adapter.Fill(table);
                    resultList.Add(table);
                }
                return resultList.ToArray();
            }
        }

        public DataTable Fill(string selectSql, params DbParameter[] parameter) => Fill(new string[] { selectSql }, new DbParameter[][] { parameter })[0];

        public DataTable[] Fill(string[] selectSqls, params DbParameter[][] parameters) => Fill(selectSqls, CommandType.Text, parameters);

        public DataTable FillWithProc(string selectSql, params DbParameter[] parameter) => FillWithProc(new string[] { selectSql }, new DbParameter[][] { parameter })[0];

        public DataTable[] FillWithProc(string[] selectSqls, params DbParameter[][] parameters) => Fill(selectSqls, CommandType.StoredProcedure, parameters);
    }

最后,完整的源程序可以到 页面下载。

那么如何使用它呢?下面我给出一些基本的使用示例,基本能满足你大部分的数据库操作需要了.
1)直接执行sql语句

版权声明:本文由bob体育app发布于编程,转载请注明出处:数据库小工具整合版