3

I've been looking through filehelpers documentation, but there doesn't seem anything to handle empty values in columns. I need to be able to set a 'non-empty' string attribute on all the columns.

Can anyone point me in the right direction?

jaffa
  • 26,770
  • 50
  • 178
  • 289
  • Your question is rather vague: How are you defining your FileHelpers record class? Are you trying to import or export? Are all your columns strings or are some of them integers, dates, etc.? – shamp00 Apr 20 '12 at 08:13
  • Yes I'm defining the record class. I'm trying to import into strings, which by default are nullable. I think that is the problem. FileHelpers doesn't have validation on empty values for strings. – jaffa Apr 20 '12 at 08:27

4 Answers4

4

You can perform any validation you want in the AfterReadRecord event. If you want to continue processing the rest of the file if there is an error, you also need to set the ErrorMode to SaveAndContinue. See below for a working example.

[DelimitedRecord("|")]
public class MyClass
{
    public string Field1;
    public string Field2;
    public string Field3;
}

class Program
{
    static void Main(string[] args)
    {
        var engine = new FileHelperEngine<MyClass>();
        engine.AfterReadRecord += new FileHelpers.Events.AfterReadHandler<MyClass>(engine_AfterReadRecord);
        engine.ErrorMode = ErrorMode.SaveAndContinue;
        // import a record with an invalid Email
        MyClass[] validRecords = engine.ReadString("Hello||World");
        ErrorInfo[] errors = engine.ErrorManager.Errors;
        Assert.AreEqual(1, engine.TotalRecords); // 1 record was processed
        Assert.AreEqual(0, validRecords.Length); // 0 records were valid
        Assert.AreEqual(1, engine.ErrorManager.ErrorCount); // 1 error was found
        Assert.That(errors[0].ExceptionInfo.Message == "Field2 is invalid");
    }

    static void engine_AfterReadRecord(EngineBase engine, FileHelpers.Events.AfterReadEventArgs<MyClass> e)
    {
        if (String.IsNullOrWhiteSpace(e.Record.Field1))
            throw new Exception("Field1 is invalid");
        if (String.IsNullOrWhiteSpace(e.Record.Field2))
            throw new Exception("Field2 is invalid");
        if (String.IsNullOrWhiteSpace(e.Record.Field3))
            throw new Exception("Field3 is invalid");
    }
}
shamp00
  • 11,106
  • 4
  • 38
  • 81
  • I've actually decided to store the valid rows from the 1st pass, and then carry my own validation on the populated class record itself, although I might go the route you suggested. Thanks for the help. Do you know where I can submit bugs to this library? I've found a bug and I'd like to send a patch (thought there might be github/bitbucket stored repo). – jaffa Apr 20 '12 at 12:52
  • Another solution would be to set `e.SkipThisRecord = true` in the `AfterReadRecord` event which just ignores the line instead of throwing an exception. – shamp00 Apr 20 '12 at 14:44
3

By default an empty string will be parsed as String.Empty in FileHelpers, but you can override this with a custom converter:

public class EmptyStringConverter : ConverterBase
{
    public override object StringToField(string sourceString)
    {
        if (String.IsNullOrWhiteSpace(sourceString))
            return null;
        return sourceString;
    }
}

Then you define your record class property like this

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

If the string corresponding to Field1 is empty or blank, it will be converted to null.

shamp00
  • 11,106
  • 4
  • 38
  • 81
  • 1
    I need this to cause an error on the row, so I could just throw an exception then? – jaffa Apr 20 '12 at 10:39
  • I see - you want to perform validation on the field and reject the record if it is null - that was not clear form your question. I'll add another answer. – shamp00 Apr 20 '12 at 11:15
  • Thanks, this helped me out with empty strings being saved as "" in the DB, they're now saving as NULL. Future note for ppl looking at this answer. – J.Z. May 14 '13 at 00:19
2

Using a Converter will not work, as FileHelpers.FieldBase checks for a zero length field, and returns Null, before invoking the Converter.

Using the public static FileHelperEngine GetEngine() ensures that the AfterReadRecord event validation is wired up correctly.

[DelimitedRecord(",")]
public class RequiredField
{
    public string Required;

    public static FileHelperEngine GetEngine()
    {
        var result = new FileHelperEngine(typeof(RequiredField));
        result.AfterReadRecord += AfterReadValidation;

        return result;
    }

    private static void AfterReadValidation(EngineBase sender, AfterReadRecordEventArgs args)
    {
        if (String.IsNullOrWhiteSpace(((RequiredField)args.Record).Required))
        {
            throw new ConvertException("RequiredField is Null or WhiteSpace", typeof(String));
        }
    }
}
Bot
  • 11,868
  • 11
  • 75
  • 131
2

I needed the same thing for one of our projects that utilizes FileHelpers heavily and contributed to provide the new FieldNotEmptyAttribute, which could be used like so:

[DelimitedRecord("|")]
public class MyClass
{
    [FieldNotEmpty()]
    public string Field1;
    public string Field2;
    [FieldNotEmpty()]
    public string Field3;
}

In the example above, if Field1 or Field3 is empty in the source file, then a ConvertException is thrown.

Jordan Parker
  • 1,208
  • 1
  • 16
  • 25