SQL bulkCopy 写入空字符串而不是 NULL

Posted

技术标签:

【中文标题】SQL bulkCopy 写入空字符串而不是 NULL【英文标题】:SQL bulkCopy writes empty string instead NULL 【发布时间】:2020-12-31 23:38:31 【问题描述】:

我有将新值插入数据库的功能:

public async Task BulkAdd(IDataReader data)

    if (Connection.State == ConnectionState.Broken || Connection.State == ConnectionState.Closed)
    
        await Connection.OpenAsync();
    
    using (SqlBulkCopy bulk = new SqlBulkCopy(Connection))
    
        bulk.DestinationTableName = GetTableName();
        bulk.BatchSize = BATCH_SIZE;
        bulk.BulkCopyTimeout = 0; // for infinity write 0
        bulk.EnableStreaming = true;
        await bulk.WriteToServerAsync(data);
    

插入字符串按顺序生成,如下所示: ,,11111,,7,,620,7 11111,04/15/2013 00:00:00,false,Bulgaria, 然后转换为CsvDataReader

var csvStreamReader = MapDataExtraWithHeaders(reader, clientId, dataExtraHeadersMap, delimiter, uploadDataId, dateFormat);
using (var csv = new CsvReader(csvStreamReader))

    csv.Configuration.BadDataFound = null;
    csv.Configuration.Delimiter = delimiter;
    

// ADDED
csv.Configuration.TypeConverterCache.AddConverter<string>(new EmptyAsNullConverter());

    var dataReader = new CsvDataReader(csv);
      csv.ReadHeader();
       if (!HeadersValid(csv.Context.HeaderRecord, DataHeaders))
             throw new CvtException(CVTExceptionCode.Import.InvalidHeaders);
   await _transactionsDataRepository.BulkAdd(dataReader);

我添加了空约束,例如:

alter table [dbo].[Extra] add constraint [DF_Custom] default (null) for [Custom]

但是,当我查看添加的内容时,我发现添加了空字符串而不是 NULL。怎么解决?

【问题讨论】:

您使用什么 CSV 库?也许您可以在列上选择将空值读取为 null。 你能把CsvDataReader传递给BulkAdd的那一行加到BulkAdd吗? 你能具体说明你使用的是哪个 CSV 库吗? 我正在使用nuget.org/packages/CsvHelper@Vernou 这个问题类似于***.com/questions/41364205/… 【参考方案1】:

您可以编写一个自定义转换器将空转换为空:

public class EmptyAsNullConverter : CsvHelper.TypeConversion.StringConverter

    public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    
        if (string.IsNullOrEmpty(text))
            return null;
        else
            return base.ConvertFromString(text, row, memberMapData);
    

感谢brandonw

使用示例:

static void Main(string[] args)

    var text =
        "a,b,c,e,f" + Environment.NewLine +
        "a,,c,e,f" + Environment.NewLine +
        "a,b,c,,f";
    using (var csv = new CsvReader(new StringReader(text), CultureInfo.InvariantCulture))
    
        csv.Configuration.TypeConverterCache.AddConverter<string>(new EmptyAsNullConverter());
        while(csv.Read())
        
            for(int i = 0; i < 5; i++)
            
                Console.Write($"csv.GetField<string>(i) ?? "null"\t");
            
            Console.WriteLine();
        
    
    Console.Read();

输出:

a       b       c       e       f
a       null    c       e       f
a       b       c       null    f

【讨论】:

你能看看我的零钱吗?我添加了这一行` csv.Configuration.TypeConverterCache.AddConverter(new EmptyAsNullConverter());` 但它没有被触发....并且值仍然写为字符串【参考方案2】:

您可以将 CSV 绑定到类并为其编写转换器。

public class EmptyStringConverter : ConverterBase

    public override object StringToField(string sourceString)
    
        if (String.IsNullOrWhiteSpace(sourceString))
            return null;
        return sourceString;
    


[FieldConverter(typeof(EmptyStringConverter))]
public string MyStrField;

【讨论】:

以上是关于SQL bulkCopy 写入空字符串而不是 NULL的主要内容,如果未能解决你的问题,请参考以下文章

Json转换空字符串而不是null

Paypal IPN 返回空字符串而不是“VERIFIED”或“INVALID”

如何使 Microsoft BCP 导出空字符串而不是 NUL 字符?

获取 pandas.read_csv 以将空值读取为空字符串而不是 nan

复选框输入返回空字符串而不是 true/false,使用 React hook dom 和 material-ui FormControlLabel

当没有匹配的记录时,如何将与另一个表连接的 group_concat 列更改为空字符串而不是 null?