开发者

How do I fix a ConvertException while importing a csv file with the filehelpers library

I am processing a csv file that occasionally has text in an int field due to user input error. It is the first column and basically it is supposed to be a unique record id. I am catching the errors using engine.ErrorManager.ErrorMode = ErrorMode.SaveAndContinue;

What I would rather do is just have the error ignored and replace the text with a numeric value of my choosing and still have that row included with the processed results.

I would even be fine with the process just sticking in the default value that I have declared in the file definition class file: [FieldNullValue(typeof(int), "0")]

One other thing is I am determining what file to parse at runtime like so:

Type t = assembly.GetType(assemblyName.Name + ".FileDefinitions." + className);  

FileHelperEngine engine = new FileHelperEngine(t);   

So I am not sure how to implement D.Lambert's suggestion in the context of what to put in for <CustomersFixedWithNumericId> So to clarify there are 7 different file definitions (class files) that get uploaded/processed, but all of them hav开发者_如何学运维e the CustomerId field.


Given the current state of FileHelpers, you really have to define that field as a string and try to do your own validation on it.

I looked at a couple different ways of addressing this -- first, I tried setting up a record using a property rather than a field. This could conceivably have allowed you to create a String property and validate inputs on the Set. This turned out to be difficult because:

  • Attributes are set to target fields only (fairly easy fix if you want to modify FileHelpers code.
  • Private fields for properties have to be marked w/ [FieldNotInFile] attribute (annoyance).
  • Properties aren't handled in RecordInfo.CreateCoreFields() method. This one is a little more involved to fix, since you really would have to create a merged list of properties and fields in the correct order. This is the point where I stopped looking into this method.

Next plan: use the record definition as-is, and validate during the read. Set up an event handler on the engine:

    engine.AfterReadRecord += new Events.AfterReadHandler<CustomersFixedWithNumericId>(engine_AfterReadRecord);
    var res = engine.ReadFile(path);

Then handle bad values in the handler:

    void engine_AfterReadRecord(EngineBase engine, Events.AfterReadEventArgs<CustomersFixedWithNumericId> e)
    {
        int intVal;
        int.TryParse(e.Record.CustomerID, out intVal);
        e.Record.CustomerID = intVal.ToString();
    }

Neither of these are perfect, but I think the second is reasonably close.

Addendum: This shows the technique above with a late-bound class:

public void TestMethod1()
{
    var assembly = System.Reflection.Assembly.GetExecutingAssembly();
    Type t = assembly.GetType("FileHelpers.Tests.CustomersFixedWithNumericId");
    FileHelperEngine engine = new FileHelperEngine(t);

    string path = @"pathtofile\BadCustomersFixedNumericId.txt";

    engine.AfterReadRecord += new Events.AfterReadHandler<object>(engine_AfterReadRecord);
    var res = engine.ReadFile(path);
}

void engine_AfterReadRecord(EngineBase engine, Events.AfterReadEventArgs<object> e)
{
    // validation here
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜