使用 FileHelpers 时如何在 SQL 服务器中将 CSV 空字符串加载为 NULL?
How can I load a CSV empty strings as a NULL in SQL Server while using FileHelpers?
我正在使用 FileHelpers 读取 CSV,目的是加载 SQL 服务器 table。
CSV 看起来像这样:
ID, SOMESTRING
"10","Blah blah"
"11",""
"12","More blah blah"
我的记录映射 class 看起来像这样:
[IgnoreFirst, DelimitedRecord(",")]
class Mytable
{
[FieldQuoted]
public ulong Id;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString;
}
最后,批量复制到数据库的代码是:
SqlBulkCopy bc = new SqlBulkCopy(mySqlConnection);
bc.DestinationTableName = "dbo.MYTABLE";
bc.WriteToServer(new FileHelperEngine<Mytable>().ReadFile(baseDir + "\" + "MYTABLE.CSV").ToDataTable<Mytable>());
最初,我没有包含 FieldNullValue 属性,但包含与否似乎并不重要。在这两种情况下,第 11 行在 SQL 服务器中作为空字符串导入。我希望它为 NULL。这能做到吗?
我不熟悉您使用的 FileHelper 包,但问题是第 11 行的值是 ""
而不是 null
。
也许你可以像这样扩展 SomeString
属性 定义
private string _SomeString;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString { get {return _SomeString;}
set {if (value == null || value.length == 0)
_SomeString = null;
else
_SomeString = value;} }
如果您的意思是使用 CsvHelper。是的,这是可以做到的。我能够测试您的场景,并且能够在使用 Microsoft SQL Server Management Studio 2014 时验证属性 SOMESTRING = NULL。
在我的示例中,使用 CsvHelper 将 CSV 文件转换为 DataTable,然后将任何空字段转换为 DBNull.Value。
使用数据库存储过程和使用用户定义的 Table 类型将修改后的数据 Table 插入数据库
最后从Database->DataTable读取,在DataGridView中查看记录。
您会注意到空字段为 NULL。
创建类型
CREATE TYPE [dbo].[MyProductTableType] AS TABLE(
[ID] [nvarchar](5) NOT NULL,
[SOMETHING] [nvarchar](128) NULL
)
创建程序:
CREATE PROCEDURE [dbo].[InsertTable]
@myTableType MyProductTableType readonly
AS
BEGIN
insert into [dbo].PRODUCTS select * from @myTableType
END
在 Windows.Forms
上使用 DataGridView 和命令按钮时的 C# 代码
using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Data.SqlClient;
using CsvHelper;
using System.IO;
namespace Stack_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var path = @"C:\Temp\MYTABLE.csv";
DataTable dt = readCSV(path);
foreach(DataRow row in dt.Rows)
{
foreach(DataColumn col in dt.Columns)
{
if (row.Field<String>(col) == String.Empty)
{
row.SetField(col, DBNull.Value); //row.SetField(col, "NULL"); // Or set the value to any string value of your choice
}
}
}
SqlConnection conn = new SqlConnection("Your SQL Connection String");
using (var command = new SqlCommand("InsertTable", conn) { CommandType = CommandType.StoredProcedure })
{
command.Parameters.Add(new SqlParameter("@myTableType", dt));
command.Connection.Open();
command.ExecuteNonQuery();
command.Dispose();
dt.Clear();
}
using(var command = new SqlCommand("Select * from PRODUCTS", conn) { CommandType = CommandType.Text})
{
SqlDataReader rdr = command.ExecuteReader();
dt.Load(rdr);
dataGridView1.DataBindings.Clear();
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
dt.Dispose();
command.Dispose();
conn.Close();
conn.Dispose();
}
} // End button1_Click
使用 CsvHelper
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
var csv = new CsvReader(new StreamReader(filePath));
// Creating the columns
typeof(Product).GetProperties().Select(p => p.Name).ToList().ForEach(x => dt.Columns.Add(x));
// Adding the rows
csv.GetRecords<Product>().ToList().ForEach(line => dt.Rows.Add(line.ID, line.SOMETHING));
return dt;
} // End readCSV : DataTable
一个class对象
public class Product
{
public string ID { get; set; }
public string SOMETHING { get; set; }
} // End class Product
SQL Server - DB Result Snapshot
使用 FileHelpers,空字符串将被解析为 String.Empty
,但您可以使用自定义转换器覆盖它:
public class EmptyStringConverter : ConverterBase
{
public override object StringToField(string sourceString)
{
if (String.IsNullOrWhiteSpace(sourceString))
return null;
return sourceString;
}
}
然后你这样定义你的记录class 属性
[FieldConverter(typeof(EmptyStringConverter))]
public string SomeString;
如果SomeString
对应的字符串为空或空白,则转为null。
我正在使用 FileHelpers 读取 CSV,目的是加载 SQL 服务器 table。
CSV 看起来像这样:
ID, SOMESTRING
"10","Blah blah"
"11",""
"12","More blah blah"
我的记录映射 class 看起来像这样:
[IgnoreFirst, DelimitedRecord(",")]
class Mytable
{
[FieldQuoted]
public ulong Id;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString;
}
最后,批量复制到数据库的代码是:
SqlBulkCopy bc = new SqlBulkCopy(mySqlConnection);
bc.DestinationTableName = "dbo.MYTABLE";
bc.WriteToServer(new FileHelperEngine<Mytable>().ReadFile(baseDir + "\" + "MYTABLE.CSV").ToDataTable<Mytable>());
最初,我没有包含 FieldNullValue 属性,但包含与否似乎并不重要。在这两种情况下,第 11 行在 SQL 服务器中作为空字符串导入。我希望它为 NULL。这能做到吗?
我不熟悉您使用的 FileHelper 包,但问题是第 11 行的值是 ""
而不是 null
。
也许你可以像这样扩展 SomeString
属性 定义
private string _SomeString;
[FieldQuoted]
[FieldNullValue(typeof(string), null)]
public string SomeString { get {return _SomeString;}
set {if (value == null || value.length == 0)
_SomeString = null;
else
_SomeString = value;} }
如果您的意思是使用 CsvHelper。是的,这是可以做到的。我能够测试您的场景,并且能够在使用 Microsoft SQL Server Management Studio 2014 时验证属性 SOMESTRING = NULL。 在我的示例中,使用 CsvHelper 将 CSV 文件转换为 DataTable,然后将任何空字段转换为 DBNull.Value。 使用数据库存储过程和使用用户定义的 Table 类型将修改后的数据 Table 插入数据库 最后从Database->DataTable读取,在DataGridView中查看记录。 您会注意到空字段为 NULL。
创建类型
CREATE TYPE [dbo].[MyProductTableType] AS TABLE(
[ID] [nvarchar](5) NOT NULL,
[SOMETHING] [nvarchar](128) NULL
)
创建程序:
CREATE PROCEDURE [dbo].[InsertTable]
@myTableType MyProductTableType readonly
AS
BEGIN
insert into [dbo].PRODUCTS select * from @myTableType
END
在 Windows.Forms
上使用 DataGridView 和命令按钮时的 C# 代码using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using System.Data.SqlClient;
using CsvHelper;
using System.IO;
namespace Stack_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var path = @"C:\Temp\MYTABLE.csv";
DataTable dt = readCSV(path);
foreach(DataRow row in dt.Rows)
{
foreach(DataColumn col in dt.Columns)
{
if (row.Field<String>(col) == String.Empty)
{
row.SetField(col, DBNull.Value); //row.SetField(col, "NULL"); // Or set the value to any string value of your choice
}
}
}
SqlConnection conn = new SqlConnection("Your SQL Connection String");
using (var command = new SqlCommand("InsertTable", conn) { CommandType = CommandType.StoredProcedure })
{
command.Parameters.Add(new SqlParameter("@myTableType", dt));
command.Connection.Open();
command.ExecuteNonQuery();
command.Dispose();
dt.Clear();
}
using(var command = new SqlCommand("Select * from PRODUCTS", conn) { CommandType = CommandType.Text})
{
SqlDataReader rdr = command.ExecuteReader();
dt.Load(rdr);
dataGridView1.DataBindings.Clear();
dataGridView1.DataSource = dt;
dataGridView1.Refresh();
dt.Dispose();
command.Dispose();
conn.Close();
conn.Dispose();
}
} // End button1_Click
使用 CsvHelper
public DataTable readCSV(string filePath)
{
var dt = new DataTable();
var csv = new CsvReader(new StreamReader(filePath));
// Creating the columns
typeof(Product).GetProperties().Select(p => p.Name).ToList().ForEach(x => dt.Columns.Add(x));
// Adding the rows
csv.GetRecords<Product>().ToList().ForEach(line => dt.Rows.Add(line.ID, line.SOMETHING));
return dt;
} // End readCSV : DataTable
一个class对象
public class Product
{
public string ID { get; set; }
public string SOMETHING { get; set; }
} // End class Product
SQL Server - DB Result Snapshot
使用 FileHelpers,空字符串将被解析为 String.Empty
,但您可以使用自定义转换器覆盖它:
public class EmptyStringConverter : ConverterBase
{
public override object StringToField(string sourceString)
{
if (String.IsNullOrWhiteSpace(sourceString))
return null;
return sourceString;
}
}
然后你这样定义你的记录class 属性
[FieldConverter(typeof(EmptyStringConverter))]
public string SomeString;
如果SomeString
对应的字符串为空或空白,则转为null。