执行NonQuery: 连接属性未初始化。

22

下午好, 我已经研究了一个问题数个小时,但还是无法解决最后的难题。以下是我正在编写的程序代码:

using System;  
using System.Collections.Generic;  
using System.Linq;  
using System.Text;  
using System.Diagnostics;  
using System.Data;  
using System.Data.SqlClient;  
using System.Configuration;  

namespace Test  
{  
  class Program  
  {  
    static void Main()  
    {  
      EventLog alog = new EventLog();  
      alog.Log = "Application";  
      alog.MachineName = ".";  
      foreach (EventLogEntry entry in alog.Entries)  
      {  
       SqlConnection connection1 = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=syslog2;Integrated Security=True");  
       SqlDataAdapter cmd = new SqlDataAdapter();  
       cmd.InsertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ");  
       cmd.InsertCommand.Parameters.Add("@EventLog",SqlDbType.VarChar).Value = alog.Log;  
       cmd.InsertCommand.Parameters.Add("@TimeGenerated", SqlDbType.DateTime).Value = entry.TimeGenerated;  
       cmd.InsertCommand.Parameters.Add("@EventType", SqlDbType.VarChar).Value = entry.EntryType;  
       cmd.InsertCommand.Parameters.Add("@SourceName", SqlDbType.VarChar).Value = entry.Source;  
       cmd.InsertCommand.Parameters.Add("@ComputerName", SqlDbType.VarChar).Value = entry.MachineName;  
       cmd.InsertCommand.Parameters.Add("@InstanceId", SqlDbType.VarChar).Value = entry.InstanceId;  
       cmd.InsertCommand.Parameters.Add("@Message", SqlDbType.VarChar).Value = entry.Message;  
       connection1.Open();  
       cmd.InsertCommand.ExecuteNonQuery();  
       connection1.Close();  
      }   
    }  
  }  
} 

代码编译通过,没有错误或警告,但当我运行它时,一旦执行到cmd.InsertCommand.ExecuteNonQuery(); ,就会出现以下错误:

ExecuteNonQuery: Connection property has not been initialized.

你有什么想法吗?我错过了什么吗?


1
cmd.InsertCommand.Connection = connection1; cmd.InsertCommand.Connection = connection1; - Alan
顺便说一句,为每个日志条目打开一个新连接是不可取的。 - Alan
@Alan 不是这样的,它们会被.NET自动池化。问题在于IDisposable对象没有在using语句中,因此如果发生异常,连接将无法返回到池中。 - IAmJersh
7个回答

53

您需要将连接分配给 SqlCommand,可以使用 构造函数 或者 属性

cmd.InsertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ");
cmd.InsertCommand.Connection = connection1;

我强烈建议在使用实现IDisposable的任何类型,如SqlConnection时,使用using-statement,它也会关闭连接:

using(var connection1 = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=syslog2;Integrated Security=True"))
using(var cmd = new SqlDataAdapter())
using(var insertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) "))
{
    insertCommand.Connection = connection1;
    cmd.InsertCommand = insertCommand;
    //.....
    connection1.Open();
    // .... you don't need to close the connection explicitely
}

除此之外,在foreach中的每个条目中,您不需要为每个条目创建新的连接和DataAdapter。即使创建、打开和关闭连接并不意味着ADO.NET将创建、打开和关闭一个物理连接,而只是查找连接池中是否有可用的连接。然而,这是一种不必要的开销。请注意保留HTML标签。

17
你没有初始化连接,这就是为什么会出现这种错误的原因。
你的代码:
cmd.InsertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ");

修正后的代码:

cmd.InsertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ",connection1);

1
实际上,当服务器建立连接但由于无法识别连接函数标识符而无法建立连接时,会出现此错误。可以通过在代码中输入连接函数来解决此问题。我举一个简单的例子来说明。在这种情况下,函数为con,你的可能不同。
SqlCommand cmd = new SqlCommand("insert into ptb(pword,rpword) values(@a,@b)",con);

1

这里有几个问题。

  1. 你真的想为每个日志条目打开和关闭连接吗?

  2. 你应该使用 SqlCommand 而不是 SqlDataAdapter 吗?

  3. 数据适配器(或 SqlCommand)需要正好像错误消息告诉你缺少的那样:一个活动连接。仅仅因为你创建了一个连接对象并不能神奇地告诉 C# 它是你想要使用的连接(特别是如果你还没有打开连接)。

我强烈推荐学习 C# / SQL Server 教程。


0

打开和关闭连接需要很长时间。正如另一个成员建议的那样,使用 "using"。 我稍微改了你的代码,但将 SQL 创建、打开和关闭放在了循环外。这应该会加速执行速度。

  static void Main()
        {
            EventLog alog = new EventLog();
            alog.Log = "Application";
            alog.MachineName = ".";
            /*  ALSO: USE the USING Statement as another member suggested
            using (SqlConnection connection1 = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=syslog2;Integrated Security=True")
            {

                using (SqlCommand comm = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ", connection1))
                {
                    // add the code in here
                    // AND REMEMBER: connection1.Open();

                }
            }*/
            SqlConnection connection1 = new SqlConnection(@"Data Source=.\sqlexpress;Initial Catalog=syslog2;Integrated Security=True");
            SqlDataAdapter cmd = new SqlDataAdapter();
            // Do it one line
            cmd.InsertCommand = new SqlCommand("INSERT INTO Application VALUES (@EventLog, @TimeGenerated, @EventType, @SourceName, @ComputerName, @InstanceId, @Message) ", connection1);
            // OR YOU CAN DO IN SEPARATE LINE :
            // cmd.InsertCommand.Connection = connection1;
            connection1.Open();

            // CREATE YOUR SQLCONNECTION ETC OUTSIDE YOUR FOREACH LOOP
            foreach (EventLogEntry entry in alog.Entries)
            {
                cmd.InsertCommand.Parameters.Add("@EventLog", SqlDbType.VarChar).Value = alog.Log;
                cmd.InsertCommand.Parameters.Add("@TimeGenerated", SqlDbType.DateTime).Value = entry.TimeGenerated;
                cmd.InsertCommand.Parameters.Add("@EventType", SqlDbType.VarChar).Value = entry.EntryType;
                cmd.InsertCommand.Parameters.Add("@SourceName", SqlDbType.VarChar).Value = entry.Source;
                cmd.InsertCommand.Parameters.Add("@ComputerName", SqlDbType.VarChar).Value = entry.MachineName;
                cmd.InsertCommand.Parameters.Add("@InstanceId", SqlDbType.VarChar).Value = entry.InstanceId;
                cmd.InsertCommand.Parameters.Add("@Message", SqlDbType.VarChar).Value = entry.Message;
                int rowsAffected = cmd.InsertCommand.ExecuteNonQuery();
            }
            connection1.Close(); // AND CLOSE IT ONCE, AFTER THE LOOP
        }

-1

试试这个...

在执行 ExecuteNonQuery() 之前,你需要使用 SqlCommand.Connection 对象上的 connection.open() 打开连接。


-1

双击您的表单以创建form_load事件。然后在该事件内部编写命令.connection = "您的连接名称";


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接