我使用Josh Close的优秀CsvHelper库读取csv文件,并使用实体框架将其加载到数据库中。这一切都很好,除了一件事;CsvReader在csv文件中将一个空字符串存储为数据库中的空字符串,我希望这是一个NULL值。因此,我所做的是创建一个自定义转换器来处理以下问题:
public class NullStringConverter : StringConverter
{
public override object ConvertFromString(TypeConverterOptions options, string text)
{
if (string.IsNullOrEmpty(text))
return null;
else
return base.ConvertFromString(options, text);
}
}
我可以通过使用流畅的映射语法或通过属性将其应用于字符串属性,现在它将插入NULL而不是空字符串。
由于我有很多包含许多字符串属性的类,所以我希望避免为每个类创建Map语句。我创建了一个通用Map类,它枚举所有属性并将自定义转换器应用于所有字符串属性。这是我迄今为止所拥有的
public class DefaultStringMap<TEntity> : CsvClassMap<TEntity> where TEntity : AbstractAmtSourceEntity
{
public DefaultStringMap()
{
typeof(TEntity).GetProperties()
.Where(p => p.PropertyType == typeof(string))
.ToList()
.ForEach(p => Map(m => p.Name).TypeConverter<NullStringConverter>());
}
}
在这里
AbstractAmtSourceEntity
是我所有实体类的基类。下面是我的读者类,它实际获取数据:
public static void Read<TEntity>(TextReader reader, AmtSourceModel context) where TEntity : AbstractAmtSourceEntity
{
using (var csvReader = new CsvReader(reader))
{
csvReader.Configuration.WillThrowOnMissingField = false;
csvReader.Configuration.Delimiter = "|";
csvReader.Configuration.SkipEmptyRecords = true;
csvReader.Configuration.RegisterClassMap<DefaultStringMap<Entity1>>();
csvReader.Configuration.RegisterClassMap<DefaultStringMap<Entity2>>();
etc...
csvReader.Configuration.IgnoreReadingExceptions = true;
csvReader.Configuration.ReadingExceptionCallback = (ex, row) =>
{
_log.Warn($"Exception caught reading row {row}", ex);
_log.Debug($"Exception detail: {ex.Data["CsvHelper"]}");
};
var records = csvReader.GetRecords<TEntity>();
context.Set<TEntity>().AddRange(records);
context.SaveChanges();
}
}
但这不起作用,映射没有应用,所以很明显我遗漏了一些东西。谁能告诉我这里缺什么?