Accessデータベースからテーブルを読み込んでから、そのテーブルのデータをいくつかのテキストファイルに並べ替えようとしています。クリンチャーは、書き込むファイル名が各レコードの値に依存することです。これは正式に私の最初のC#アプリケーションであるため、私を「グリーン」と見なすことができます。また、コードを打ち出すことができるようになるまで、Accessデータベースで作業していることにも言及する必要があります。最終的には、数百万のレコードを持つSQLサーバーからプルされます。
私は今コードを動作させていますが、問題はファイルのオープン/クローズ操作がたくさんあることです。これらのファイルはネットワークドライブに書き込まれるため、書き込み用に各ファイルを1回だけ開きます。これは基本的にサーバー上で実行される接着剤アプリです-したがって、他にもいくつかの制限があります-ローカルドライブに保存してからネットワークにコピーすることはできません。プルする前にクエリを並べ替えることができません。実行中にサーバーリソースに悪影響を与えることはできません。
おそらくこれを行うための最良の方法は、ハッシュテーブルを使用することです。ファイルが開かれているかどうかを確認し、開かれていない場合は、ファイルを開いてファイルハンドルをハッシュテーブルに保存します。その後、終了したら一度にすべて閉じます。ただし、複数のStreamWriterオブジェクトを同時に使用する方法の例を見つけることができません。
私はこれに対する答えを比較的簡単に見つけることを期待していましたが、彼の解決策を見つけることができないようです。私の疑いは、StreamWriterがこれに使用するのに間違ったクラスであるということです。
私が見つけた最も近い前の質問は、CodeProjectページからのものです。そのページでは、ファイルの手を開いたままにしておくことは悪いことであり、避けるべきであると彼らは言っていますが、そのページは理由を説明しておらず、代替例も提供していません。データセット全体をメモリにロードしてから操作することをお勧めしますが、テーブルにデータが多すぎるため、これはオプションではありません。
これが私がこれまでに持っているものです。
String strConnection;
String strQuery;
String strPunchFileNameTemplate;
// Define our Variables
strConnection = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=ClockData.accdb";
strQuery = @"SELECT * FROM ClockPunches";
strPunchFileNameTemplate = @"C:\PUNCHES\%READER%.TXT";
// OleDbConnection implements iDisposable interface, so we must scope out its usage.
// Set up Connection to our data source
using (OleDbConnection ConnObj = new OleDbConnection(strConnection)) {
// Create a Command with our Query String
OleDbCommand CmdObj = new OleDbCommand(strQuery,ConnObj);
// Open our Connection
ConnObj.Open();
// OledbDataReader implements iDisposable interface, so we must scope out its usage.
// Execute our Reader
using (OleDbDataReader ReaderObj = CmdObj.ExecuteReader(CommandBehavior.KeyInfo)) {
// Load the source table's schema into memory (a DataTable object)
DataTable TableObj = ReaderObj.GetSchemaTable();
// Parse through each record in the Reader Object
while(ReaderObj.Read()) {
// Extract PunchTime, CardNumber, and Device to separate variables
DateTime dtTime = ReaderObj.GetDateTime(ReaderObj.GetOrdinal("PunchTime"));
Int16 intID = ReaderObj.GetInt16(ReaderObj.GetOrdinal("CardNumber"));
String strReader = ReaderObj.GetString(ReaderObj.GetOrdinal("Device"));
// Translate the device name into a designated filename (external function)
strReader = GetDeviceFileName(strReader);
// Put our dynamic filename into the path template
String pathStr = strPunchFileNameTemplate.Replace("%READER%",strReader);
// Check to see if the file exists. New files need an import Header
Boolean FileExistedBool = File.Exists(pathStr);
// StreamWrite implements iDisposable interface, so we must scope out its usage.
// Create a Text File for each Device, Append if it exists
using (StreamWriter outSR = new StreamWriter(pathStr, true)) {
// Write our Header if required
if (FileExistedBool == false) {
outSR.WriteLine("EXAMPLE FILE HEADER");
}
// Set up our string we wish to write to the file
String outputStr = dtTime.ToString("MM-dd-yyyy HH:mm:ss") + " " + intID.ToString("000000");
// Write the String
outSR.WriteLine(outputStr);
// End of StreamWriter Scope - should automatically close
}
}
// End of OleDbDataREader Scope - should automatically close
}
// End of OleDbConnection Scope - should automatically close
}