2016-09-09 5 views
0

Josh Closeの優れたCsvHelperライブラリを使用して、csvファイルを読み込み、エンティティフレームワークを使用してデータベースに読み込みます。これはすべて1つのことを除いてうまくいく。 CsvReaderは空の文字列をデータベースに空の文字列としてcsvファイルに保存します。代わりにこの値をNULL値にします。それでは、私がやったことは、このの世話をするカスタムコンバータの作成です:クラスのセットのすべての文字列プロパティにCsvHelperカスタムコンバータを適用します。

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クラスを作成しました。ここで私はここでSOFAR

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(); } } これは動作しませんが、マッピングが適用されないので、明らかに私は何かが不足しています。誰が私にここで行方不明を教えてもらえますか?

答えて

2

コンバータはグローバルに設定できます。

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

これは私が探していたものです。 – Hintham

+0

最新版(2.16.3)でStringConverterのグローバルオーバーライドが動作しません。質問に記載されているようにコンバータを明示的に指定するとうまく動作します。 –

関連する問題