如何在C#OdbcCommand对象中使用变量执行多个语句

时间:2018-01-25 12:37:01

标签: mysql .net ado.net odbc

我想通过C#中的OdbcCommand对象一次执行MySql查询以下作为动态查询,它总是失败:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; 

set @row=0;  

select * from 
                    (

select @row:=@row+1  as my____row_num,
cities.`cityid`,
cities.`cityname`,
cities.`countryid`,
cities.`countryname` , '1' as my____data_row_created  , '1' as 
my____data_row_updated  from `cities`    ) p
                    where my____row_num>=101 and  my____row_num<=200;  

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

我使用以下方法执行上述MySql查询:

 ExcuteCommand(Sql)
    {
        DataTable dt = new DataTable();
        OdbcCommand SQLCommand = new OdbcCommand(Sql);
        OdbcConnection Con = new OdbcConnection(ConnectionString);
        try
        {
            Con.Open();
            SQLCommand.Connection = Con;
            OdbcDataAdapter da = new OdbcDataAdapter(SQLCommand);
            da.Fill(dt);
            Con.Close();
            Con.Dispose();
        }
        catch
        {
            try
            {
                Con.Close();
            }
            catch { }

            throw;
        }
        return dt;
    }

3 个答案:

答案 0 :(得分:1)

我不打算尝试解决你的MySql问题(几乎所有我的SQL都是SQL Server的),但你的c#代码可以而且应该写得更好,而且由于评论不适合代码,我想我最好把它写成答案,(冒着被低估并被标记为非答案的风险)。

所以这是对你的c#部分的改进:

DataTable FillDataTable(string Sql)
{
    var dataTable = new DataTable();
    using(var con = new OdbcConnection(ConnectionString))
    {
        using(var command =  new OdbcCommand(Sql, con))
        {
            using(var dataAdapter = new OdbcDataAdapter(SQLCommand))
            {
                dataAdapter.Fill(dataTable);
            }
        }
    }
    return dataTable;
}

兴趣点:

  • 我已将您的方法重命名为更具描述性的名称。 ExecuteCommand没有说明此方法的作用。 FillDataTable是不言自明的。

  • using语句确保处理实现IDisposable接口的实例 - 几乎所有ADO.Net类都在实现它。 处理OdbcConnection也会将其关闭,因此您无需自己明确关闭它。

  • 如果你没有对它们做任何事情,就没有必要捕捉异常。拇指规则是throw early, catch late.(实际上,只要您可以执行某些操作,例如写入日志,向用户显示消息,重试等等)。

  • DataAdapters隐式打开Connection对象,无需显式打开它。

您可以做的其他两项改进是:

  1. 此方法也接受参数。

  2. 此方法也接受CommandType作为参数(目前,使用存储过程不起作用,因为CommandType的默认值为Text

  3. 所以,更好的版本是:

    DataTable FillDataTable(string Sql, CommandType commandType, params OdbcParameter[] parameters)
    {
        var dataTable = new DataTable();
        using(var con = new OdbcConnection(ConnectionString))
        {
            using(var command =  new OdbcCommand(Sql, con))
            {
                command.CommandType = commandType;
                command.Parameters.AddRange(parameters);
                using(var dataAdapter = new OdbcDataAdapter(SQLCommand))
                {
                    dataAdapter.Fill(dataTable);
                }
            }
        }
        return dataTable;
    }
    

    如果你想进一步改进,你可以查看我的GitHub ADONETHelper项目 - 我有一个Execute的私有方法,以及填充数据表的方法,填充数据集,执行非查询等都使用这种方法。

答案 1 :(得分:1)

我从here找到了解决方案。在C#中通过ODBC执行多个动态MySql语句时,我们有两个选择:

  1. 单独执行每个命令
  2. 使用存储过程
  3. 在我的情况下,我一定会使用动态quire,因为我只对数据库进行读访问。

    <强>解决方案: 我使用另一种技术将会话变量用作派生表,并将其与主表交叉连接,而不是声明变量并设置它。请参阅以下查询,在我的方案中,我更改为MySql查询代码,并从查询中删除了两个SET SESSION相关代码,并且它正常工作:

    select * from 
                            (
    
        select @row:=@row+1  as my____row_num,
        cities.`cityid`,
        cities.`cityname`,
        cities.`countryid`,
        cities.`countryname` , '1' as my____data_row_created  , '1' as 
        my____data_row_updated  from `cities` ,(select @row:=0) as t      ) p
                            where my____row_num>=101 and  my____row_num<=200; 
    

答案 2 :(得分:0)

请你试试这个

declare @row int
    set @row=0;  
    select * from 
                        (

    select SUM(@row,1) as my____row_num,
    cities.cityid as CityID,
    cities.cityname as CityName,
    cities.countryid as CountryID,
    cities.countryname as CountryName , 

    '1' as my____data_row_created  , '1' as my____data_row_updated  from cities) //i did not understand the meaning of this

    where (my____row_num BETWEEN 100 AND 200 ) 

后端

 ExcuteCommand(Sql)
    {
<AddThis>ConnectionString= ConfigurationManager.ConnectionStrings["YourDataBaseLocation_OR_theConnectionCreatedViaProperties"].Connectionstring;</AddThis>
        DataTable dt = new DataTable();
     <deleteThis>   OdbcCommand SQLCommand = new OdbcCommand(Sql);</deletethis>
//You Need to add the connection you have used it and Odbc

//Command.CommandType= CommandType.StoredProcedure();
        OdbcConnection Con = new OdbcConnection(ConnectionString);
<AddThis>OdbcCommand SqlCommand  = new OdbcCommand(Sql,Con);</AddThis>
        try
        {
            Con.Open();
            SQLCommand.Connection = Con;
            OdbcDataAdapter da = new OdbcDataAdapter(SQLCommand);
            da.Fill(dt);
<add this > SQLCommand.ExecuteNonQuery();</Add this>
            Con.Close();
           <delete> Con.Dispose();</delete>
        }
        catch
        {
            try
            {
                Con.Close();
            }
            catch (Exception e) { }

            throw (e);
        }
        return dt;
    }