午後、だから私は何時間もこの1つの問題に取り組んでおり、実際にこの最後のこぶを乗り越えることはできません。以下は、私が書いているこのプログラムのコードです。
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:接続プロパティは初期化されていません。
私が逃したものに関するアイデアはありますか?
接続をSqlCommand
に割り当てる必要があります。 constructor または property を使用できます。
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
}
それとは別に、新しい接続を作成する必要はなく、DataAdapter
のすべてのエントリにforeach
を作成する必要はありません。接続の作成、オープン、クローズはnotは、ADO.NETがphysical接続を作成、オープン、およびクローズしますが、利用可能な接続について connection-pool を調べるだけです。それにもかかわらず、それは不必要なオーバーヘッドです。
接続を初期化していないので、この種のエラーが発生します。
あなたのコード:
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);
ここでいくつか間違っています。
ログエントリごとに接続を開いたり閉じたりしますか?
SqlCommand
の代わりにSqlDataAdapter
を使用するべきではありませんか?
データアダプター(またはSqlCommand
)には、エラーメッセージに表示されていないこと、つまりアクティブな接続が正確に必要です。接続オブジェクトを作成したからといって、それが使用したいものであることを魔法のようにC#に伝えません(特に、接続を開いていない場合)。
C#/ SQL Serverチュートリアルを強くお勧めします。
実際、このエラーは、サーバーが接続したが、接続関数識別子の識別に失敗したために構築できない場合に発生します。この問題は、コードに接続関数を入力することで解決できます。このために、簡単な例を取り上げます。この場合、関数はconであり、異なる場合があります。
SqlCommand cmd = new SqlCommand("insert into ptb(pword,rpword) values(@a,@b)",con);
接続のオープンとクローズには多くの時間がかかります。そして、別のメンバーが提案したように「使用」を使用します。コードを少し変更しましたが、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
}