Search code examples
c#csvhelper

CsvHelper no longer has Context.IsFieldBad


I'm upgrading a program from CsvHelper v2.15.0 to v33.0.1 and dealing with all the changes. I've fixed most of them, but I can't find the solution to this. In my old code I have:

while (csv.Read() && !csv.Context.IsFieldBad)
 {
   ..
 }

This worked in v2.15, but in v33, IsFieldBad is no longer a member of the Context, and I can't find anything online that discusses this issue. I've gone thought the CsvHelper Migration steps, as well as the overall Change Log, and even peered into the source, and nothing mentions this breaking change (that I can see or understand).

What would be the equivalent to this code for the latest CsvHelper version?


Solution

  • I'm not positive on this, but I believe IsFieldBad was removed in favor of throwing a BadDataException. To upgrade this code, you would need to wrap the while loop in a try/catch. And depending on what IsFieldBad used to cover, you may also have to catch MissingFieldException.

    try
    {
        while (csv.Read())
        {
            var record = csv.GetRecord<Foo>();
    
            results.Add(record);
    
        }
    }
    catch (BadDataException ex)
    {
        Console.WriteLine("BadDataFound on row " + ex.Context.Parser.Row);
    }
    

    If you didn't want to have an exception thrown, you could use the BadDataFound property in CsvConfiguration to set your own IsFieldBad variable. The difference being that csv.Read() doesn't throw the BadDataException. That happens when you actually try to access the data with something like csv.GetRecord<T>(). Depending on what IsFieldBad used to cover, you might also have to set MissingFieldFound in CsvConfiguration.

    void Main()
    {
        var data = @"Id,Name
    1,Good Name
    2,Bad "" Name
    3,Another Good Name";
    
        var isFieldBad = false;
        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            BadDataFound = row => {
                isFieldBad = true;
                Console.WriteLine("BadDataFound on row " + row.Context.Parser.Row);
            }       
        };
    
        var reader = new StringReader(data);
        using var csv = new CsvReader(reader, config);
        
        csv.Read();
        csv.ReadHeader();
        
        var results = new List<Foo>();
        
        while (csv.Read())
        {
            var record = csv.GetRecord<Foo>();
            
            if (isFieldBad)
            {
                isFieldBad = false;
                continue;
            }
    
            results.Add(record);        
        }
        
        results.Dump();
    }
    
    public class Foo
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }