坑:关于 MySqlClientFactory 没实现 CreateDataAdapter() 方法

情景

在使用数据库通用类 DBHelper 操作 MySql 获取 DataTable 时,DataTable 恒为 null

过程

先看看 DBHelper 获取 DataTable 的代码。

public DataSet ExecuteDataSet(DbCommand cmd)
{
    var dbfactory = DbProviderFactories.GetFactory(DbProviderName);
    var dbDataAdapter = dbfactory.CreateDataAdapter();

    if (dbDataAdapter == null) return null;

    dbDataAdapter.SelectCommand = cmd;
    var ds = new DataSet();
    dbDataAdapter.Fill(ds);
    return ds;
}

源码中使用了 Factory.CreateDataAdapter() 获取 DbDataAdapter,再由 DbDataAdapter 将数据填充到 DataTable,并返回 DataTable。

跟踪 DbFactory 和 DbDataAdapter,发现 DbDataAdapter 为 null。

var factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
var da = factory.CreateDataAdapter();

var f_mysql = MySqlClientFactory.Instance;
var da_mysql = f_mysql.CreateDataAdapter();

额,DbDataAdapter 为 null ?骗人的吧,既然为 null,CreateDataAdapter() 还有啥用?

对比下 CreateDataAdapter() 分别在 Oracle 和 Sqlite 中的情况。

var factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
var da = factory.CreateDataAdapter();

var f_mysql = MySqlClientFactory.Instance;
var f_mssql = SqlClientFactory.Instance;
var f_sqlite = SQLiteFactory.Instance;
var f_oracle = OracleClientFactory.Instance;

var da_mysql = f_mysql.CreateDataAdapter();
var da_mssql = f_mssql.CreateDataAdapter();
var da_sqlite = f_sqlite.CreateDataAdapter();
var da_oracle = f_oracle.CreateDataAdapter();

输入图片说明

看看反编译代码,唯独MySQLClientFactory没实现 CreateDataAdapter() 方法

唯独MySQLClientFactory没实现

结论

<p style="text-decoration: underline;">MySqlDataAdapter>MySqlDataAdapter 不能由 MySqlClientFactory.CreateDataAdapter() 实例化。</p> 其实只是 config 文件没配置好……

其他

public DataSet ExecuteDataSet(DbCommand cmd)
{
    var dbfactory = DbProviderFactories.GetFactory(DbProviderName);
    var dbDataAdapter = dbfactory.CreateDataAdapter();

    if (dbDataAdapter == null)
    {
        if ("MySql.Data.MySqlClient" == DbProviderName)
        {
            dbDataAdapter = (DbDataAdapter) Assembly.Load("MySql.Data")
                .CreateInstance("MySql.Data.MySqlClient.MySqlDataAdapter");
        }
        else
        {
            return null;
        }
    }

    if (dbDataAdapter == null)
        return null;

    dbDataAdapter.SelectCommand = cmd;
    var ds = new DataSet();
    dbDataAdapter.Fill(ds);
    return ds;
}

参考

转载于:https://my.oschina.net/u/868789/blog/1819037

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
private SqlConnection con; //数据库连接、关闭、释放资源 #region 数据库连接、关闭、释放资源 private void Open() { if (con == null) { //根据Web.Config文件中数据库连接串,建立数据连接 con = new SqlConnection(ConfigurationManager.ConnectionStrings["ApplicationServices"].ToString ()); } try { //判断连接对象状态,如果是关闭,将其打开 if (con.State == System.Data.ConnectionState.Closed) con.Open(); } catch (System.Data.SqlClient.SqlException E) { //如果出现错误,关闭数据连接,并抛出错误信息 this.Close(); throw new Exception(E.Message); } } public void Close() { if (con != null) { con.Close();//关闭连接 } } public void Dispose() { if (con != null) { con.Dispose();//释放连接资源 con = null; } } #endregion #region 参数处理 public SqlParameter MakeInParam(string ParamName, SqlDbType DbType, int Size, object Value) //参数处理 { SqlParameter param; if (Size > 0) { param = new SqlParameter(ParamName, DbType, Size); } else { param = new SqlParameter(ParamName, DbType); } param.Direction = ParameterDirection.Input; if (Value != null) { param.Value = Value; } return param; } #endregion #region 将参数添加到SqlCommand当中 private SqlCommand CreateCommand(string procName, SqlParameter[] prams) //将参数添加到SqlCommand当中 { this.Open();//确认打开连接 SqlCommand cmd = new SqlCommand(procName, con); cmd.CommandType = CommandType.Text; //执行类型是命令文本。上面的参数procName即为SQL语句 //cmd.CommandType = CommandType.StoredProcedure; //执行类型是存储过程。上面的参数procName即为存储过程名称 //下面依次把参数传入命令文本 if (prams != null) { foreach (SqlParameter parameter in prams) cmd.Parameters.Add(parameter); } return cmd; } #endregion #region 将参数添加到SqlDataAdapter当中 private SqlDataAdapter CreateDataAdapter(string procName, SqlParameter[] prams) //将参数添加到SqlDataAdapter当中 { this.Open(); SqlDataAdapter dap = new SqlDataAdapter(procName, con); dap.SelectCommand.CommandType = CommandType.Text;//执行类型:命令文本 //dap.SelectCommand.CommandType = CommandType.StoredProcedure;//执行类型:存储过程 if (prams != null) { foreach (SqlParameter parameter in prams) { dap.SelectCommand.Parameters.Add(parameter); } } return dap; } #endregion #region 针对查询(带参) public DataSet RunProcReturn(string procName, SqlParameter[] prams, string tbName) //针对查询(带参) { SqlDataAdapter dap = CreateDataAdapter(procName, prams); DataSet ds = new DataSet(); dap.Fill(ds, tbName); this.Close(); //得到执行成功返回值 return ds; } #endregion #region 针对查询(不带参) public DataSet RunProcReturn(string procName, string tbName) //针对查询(不带参) { SqlDataAdapter dap = CreateDataAdapter(procName, null); DataSet ds = new DataSet(); dap.Fill(ds, tbName); this.Close(); //得到执行成功返回值 return ds; } #endregion #region 针对增删改 public int RunProc(string procName, SqlParameter[] prams) //针对增删改 { SqlCommand cmd = CreateCommand(procName, prams); int i = cmd.ExecuteNonQuery(); this.Close(); return i; } #endregion }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值