代码之家  ›  专栏  ›  技术社区  ›  Hintham

将CsvHelper自定义转换器应用于一组类的所有字符串属性

  •  1
  • Hintham  · 技术社区  · 8 年前

    我使用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(); } } 但这不起作用,映射没有应用,所以很明显我遗漏了一些东西。谁能告诉我这里缺什么?

    1 回复  |  直到 8 年前
        1
  •  3
  •   Josh Close    8 年前

    您可以全局设置转换器。

    TypeConverterFactory.AddConverter( typeof( string ), new NullStringConverter() );
    // or
    TypeConverterFactory.AddConverter<string>( new NullStringConverter() );