首先,我的程序应该将 CSV 文件的内容附加到 SQL Server 中的 SQL 表中,当您使用文本框“pathInputTextBox”中输入的路径和文本框“tableInputTextBox”中的表名称时按按钮“toSqlButton”。完成这部分后,我还将使用不同的按钮针对不同类型的数据库执行此操作,但目前读取 csv 文件已经失败。 (我什至不知道它之后是否可以正确附加数据,但我是一个愚蠢的小伙子,先编写所有代码,然后解决一个又一个问题,所以当我到达那里时我会跨过那座桥。 )
错误是:
CsvHelper.ReaderException: 'No header record was found.
IReader state:
ColumnCount: 0
CurrentIndex: -1
HeaderRecord:
从线上
csv.ReadHeader();
在 toSQLButton_Click 事件中。通过调试,我发现这是由于 ReadCSV 方法返回 null 造成的,每当读取文件失败时都会返回 null。
我尝试解决此问题的一些方法包括编写不同的方法来读取文件(例如 TextReader),这些方法仍然可以使用类似的语法和编写
CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) {Delimiter = ";", HasHeaderRecord = true });
而不是
CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture);
但这些似乎都不起作用。我 100% 确信我写入文本框的文件路径应该有效(是的,我在将其复制到文件资源管理器中后删除了“s)。我已经在互联网上进行了筛选并向 ChatGPT 寻求帮助,但我在我的智慧结束了,感觉这一定是一些非常微小的、愚蠢的菜鸟错误,被植入到代码中的某个地方,应该是显而易见的。请帮助我,我期待您的回复。
代码:
/// <summary>
/// Reads the CSV file specified by the data path and returns CsvReader information.
/// </summary>
/// <param name="pathString"></param> Data path of the CSV file.
/// <returns> CsvReader information of the CSV file or null in case of failure. </returns>
private CsvReader ReadCSV(string pathString)
{
try
{
var reader = new StreamReader(pathString);
CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
reader.Close();
return csv;
}
catch (FileNotFoundException)
{
MessageBox.Show("File not found. Please check the entered file path.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while reading the CSV file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return null;
}
/// <summary>
/// Writes the content of the CSV file from the pathInputTextBox to the SQL Server on toSqlButton click.
/// </summary>
/// <param name="sender"></param> Sender information.
/// <param name="e"></param> Event stuff.
private void toSqlButton_Click(object sender, EventArgs e)
{
string sqlConnection = "Data Source=VERYCOOLDATASOURCE\\SQLEXPRESS;Initial Catalog=VeryCoolDB;Integrated Security=True";
CsvReader csv = ReadCSV(pathInputTextBox.Text);
if (csv != null)
{
using(SqlConnection sqlconn = new SqlConnection(sqlConnection))
{
// Get CSV column names for comparison
csv.ReadHeader();
List<string> csvColumns = csv.HeaderRecord.ToList() ?? new List<string>();
if (csvColumns.Count == 0)
{
MessageBox.Show("CSV file has no readable columns. Subsequent errors are to be expected.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
// Get SQL column names for comparison
List<string> sqlColumns = GetSQLColumns(sqlConnection, $"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{tableInputTextBox.Text}'");
// Compare columns
if (csvColumns.All(sqlColumns.Contains) && csvColumns.Count == sqlColumns.Count)
{
try
{
sqlconn.Open();
using (SqlTransaction sqltrans = sqlconn.BeginTransaction())
using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlconn, SqlBulkCopyOptions.KeepIdentity, sqltrans))
{
sqlcopy.DestinationTableName = tableInputTextBox.Text;
CsvDataReader csvdata = new CsvDataReader(csv);
sqlcopy.WriteToServer(csvdata);
sqltrans.Commit();
}
sqlconn.Close();
}
catch (Exception ex)
{
MessageBox.Show("An error occurred while writing the data: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("Columns of the CSV file and columns of the SQL table do not match.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
else
{
MessageBox.Show("The file could not be read.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
static List<string> GetSQLColumns(string connectionString, string query)
{
List<string> columns = new List<string>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(query, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
columns.Add(reader["COLUMN_NAME"].ToString());
}
reader.Close();
connection.Close();
}
return columns;
}
CSV 文件的内容:
mitid; vname; nname; gehalt; geburtsdatum
5; bingus; bongus; 1223.23; 2010-01-01;
6; bongus; bingus; 1223.23; 2010-01-01;
如果您想创建一个返回 CsvReader 供以后使用的方法,则在将其返回给使用者之前无法关闭读取器实例。
更改此:
var reader = new StreamReader(pathString);
CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
reader.Close();
return csv;
对此:
var reader = new StreamReader(pathString);
return new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
请记住,您的设计可能不太理想。例如,您拥有的第二个 catch 块:
catch (Exception ex)
{
MessageBox.Show("An error occurred while reading the CSV file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
相当具有误导性,因为在此方法中您根本没有开始读取 CSV:您稍后在实际使用其外部的
CsvReader
实例时会这样做。