【问题标题】:How to directly execute SQL query in C#?如何在 C# 中直接执行 SQL 查询?
【发布时间】:2014-03-09 16:17:43
【问题描述】:

好的,我有一个旧的批处理文件可以满足我的需要。但是,如果没有新的管理,我们将无法再运行批处理文件,因此我需要使用 C# 启动。

我正在使用 Visual Studio C#,并且已经为我需要构建的应用程序设置了表单。 (我边走边学)

这是我需要在 C# 中完成的任务(这是批处理内容)

sqlcmd.exe -S .\PDATA_SQLEXPRESS -U sa -P 2BeChanged! -d PDATA_SQLEXPRESS  -s ; -W -w 100 -Q "SELECT tPatCulIntPatIDPk, tPatSFirstname, tPatSName, tPatDBirthday  FROM  [dbo].[TPatientRaw] WHERE tPatSName = '%name%' "

基本上它使用SQLCMD.exe 和已经存在的名为PDATA_SQLExpress 的数据源。
我已经搜索并接近了,但我仍然不知道从哪里开始。

【问题讨论】:

  • 您是要执行现有的批处理文件,还是要连接到数据库并直接在 C# 中运行查询?

标签: c# .net sql-server batch-file


【解决方案1】:

要直接从 C# 中执行命令,您可以使用 SqlCommand 类。

使用参数化 SQL(以避免注入攻击)的快速示例代码可能如下所示:

string queryString = "SELECT tPatCulIntPatIDPk, tPatSFirstname, tPatSName, tPatDBirthday  FROM  [dbo].[TPatientRaw] WHERE tPatSName = @tPatSName";
string connectionString = "Server=.\PDATA_SQLEXPRESS;Database=;User Id=sa;Password=2BeChanged!;";

using (SqlConnection connection = new SqlConnection(connectionString))
{
    SqlCommand command = new SqlCommand(queryString, connection);
    command.Parameters.AddWithValue("@tPatSName", "Your-Parm-Value");
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    try
    {
        while (reader.Read())
        {
            Console.WriteLine(String.Format("{0}, {1}",
            reader["tPatCulIntPatIDPk"], reader["tPatSFirstname"]));// etc
        }
    }
    finally
    {
        // Always call Close when done reading.
        reader.Close();
    }
}

【讨论】:

  • nate,我想我现在可能倾向于这个方向。到目前为止,它似乎可以工作,但是在运行它时我得到了一个未处理的异常。无效的对象 namd 'dbo.TPatientRaw'。
  • @Reracer68 我怀疑 SQL 查询有问题。尝试在查询中使用表名TPatientRaw,而不是完整的[dbo].[Table]
  • 知道了!不得不给一个数据库使用,因为有多个!奇迹般有效。甚至指出它将结果输出到富文本框。
  • 在SqlConnection 上使用 而不是在SqlDataReader 上是否有任何原因?
  • @Fa773NM0nK 除了样品之外没有什么好的理由,我忘记了。对于任何想知道的人,这里有一个很好的阅读为什么它是一个好主意:stackoverflow.com/questions/3386770/using-on-sqldatareader
【解决方案2】:

这样的事情就足够了,做你的批处理文件正在做的事情(将结果集作为分号分隔的文本转储到控制台):

// sqlcmd.exe
// -S .\PDATA_SQLEXPRESS
// -U sa
// -P 2BeChanged!
// -d PDATA_SQLEXPRESS
// -s ; -W -w 100
// -Q "SELECT tPatCulIntPatIDPk, tPatSFirstname, tPatSName, tPatDBirthday  FROM  [dbo].[TPatientRaw] WHERE tPatSName = '%name%' "

DataTable dt            = new DataTable() ;
int       rows_returned ;

const string credentials = @"Server=(localdb)\.\PDATA_SQLEXPRESS;Database=PDATA_SQLEXPRESS;User ID=sa;Password=2BeChanged!;" ;
const string sqlQuery = @"
  select tPatCulIntPatIDPk ,
         tPatSFirstname    ,
         tPatSName         ,
         tPatDBirthday
  from dbo.TPatientRaw
  where tPatSName = @patientSurname
  " ;

using ( SqlConnection connection = new SqlConnection(credentials) )
using ( SqlCommand    cmd        = connection.CreateCommand() )
using ( SqlDataAdapter sda       = new SqlDataAdapter( cmd ) )
{
  cmd.CommandText = sqlQuery ;
  cmd.CommandType = CommandType.Text ;
  connection.Open() ;
  rows_returned = sda.Fill(dt) ;
  connection.Close() ;
}

if ( dt.Rows.Count == 0 )
{
  // query returned no rows
}
else
{

  //write semicolon-delimited header
  string[] columnNames = dt.Columns
                           .Cast<DataColumn>()
                           .Select( c => c.ColumnName )
                           .ToArray()
                           ;
  string   header      = string.Join("," , columnNames) ;
  Console.WriteLine(header) ;

  // write each row
  foreach ( DataRow dr in dt.Rows )
  {

    // get each rows columns as a string (casting null into the nil (empty) string
    string[] values = new string[dt.Columns.Count];
    for ( int i = 0 ; i < dt.Columns.Count ; ++i )
    {
      values[i] = ((string) dr[i]) ?? "" ; // we'll treat nulls as the nil string for the nonce
    }

    // construct the string to be dumped, quoting each value and doubling any embedded quotes.
    string data = string.Join( ";" , values.Select( s => "\""+s.Replace("\"","\"\"")+"\"") ) ;
    Console.WriteLine(values);

  }

}

【讨论】:

    【解决方案3】:

    重要提示:除非您完全信任用户,否则不应连接 SQL 查询。查询连接涉及 SQL 注入被用来接管世界、...khem、您的数据库的风险。

    如果您不想详细说明如何使用SqlCommand 执行查询,那么您可以像这样调用相同的命令行:

    string userInput = "Brian";
    var process = new Process();
    var startInfo = new ProcessStartInfo();
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.FileName = "cmd.exe";
    startInfo.Arguments = string.Format(@"sqlcmd.exe -S .\PDATA_SQLEXPRESS -U sa -P 2BeChanged! -d PDATA_SQLEXPRESS  
         -s ; -W -w 100 -Q "" SELECT tPatCulIntPatIDPk, tPatSFirstname, tPatSName,
         tPatDBirthday  FROM  [dbo].[TPatientRaw] WHERE tPatSName = '{0}' """, userInput);
    
    process.StartInfo = startInfo;
    process.Start();
    

    只需确保将每个双引号 " 转义为 ""

    【讨论】:

    • 哇,真快!这正是我想要的!
    • 快速提问。我将如何向其中添加用户输入?从一个名为 GFIDuserinput 的文本框中以相同的形式说?在实际的 sqlcmd.exe 字符串中,%name% 是需要提供的。
    • @Reracer68 - 在您上面提到的情况下,您可以连接文本框的 .Text 属性中的 %name% 值。
    • 我不建议直接连接用户输入,除非你想容易受到 SQL 注入的攻击。
    • 现在这不是一个真正的问题。这些是封闭的网络,没有像这样的真正安全威胁。不过这很酷。我应该可以从这里拿走它。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多