CsvHelper icon indicating copy to clipboard operation
CsvHelper copied to clipboard

Can't find NamedIndexCache and NamedIndexes

Open YanaFloryanovich opened this issue 4 years ago • 15 comments

Updated csvhelper from 19.0.0 to 27.1.1. Now I can't find NamedIndexCache and NamedIndexes in Context. Where are they located? If removed, have they been replaced? And has IWriterConfiguration.QuoteString been replaced?

YanaFloryanovich avatar Aug 23 '21 18:08 YanaFloryanovich

The name index caches are internal now. How are you using them?

QuoteString is internal now and called escapeQuoteString. There is also escapeDelimiterString and escapeNewlineString that are used when writing in Escape mode.

JoshClose avatar Aug 23 '21 19:08 JoshClose

HeaderValidated = args => { var cashedHeaderNames = args.Context.NamedIndexCache.Values.Select(x => x.Item1); var headerNames = args.Context.NamedIndexes.Keys; var areHeadersEqual = headerNames.SequenceEqual(cashedHeaderNames); };

YanaFloryanovich avatar Aug 23 '21 19:08 YanaFloryanovich

What are you using areHeadersEqual for? Maybe we can accomplish the same thing in another way.

JoshClose avatar Aug 23 '21 19:08 JoshClose

HeaderValidated = args =>
    {
        var cashedHeaderNames = args.Context.NamedIndexCache.Values.Select(x => x.Item1);

        var headerNames = args.Context.NamedIndexes.Keys;

        var areHeadersEqual = headerNames.SequenceEqual(cashedHeaderNames);
        if (!areHeadersEqual)
        {
            throw new CsvManagerException("File header has wrong column order");
        }
    };

YanaFloryanovich avatar Aug 23 '21 19:08 YanaFloryanovich

Are you doing multiple files in a row and want to know if a file has a different column order?

JoshClose avatar Aug 23 '21 19:08 JoshClose

@JoshClose If I am not mistaken, it just checks ordering in single file. image Let me check it properly.

YanaFloryanovich avatar Aug 24 '21 10:08 YanaFloryanovich

@JoshClose I used this for validation for checking csv header column order during importing csv file to sure that nothing was missed or swapped. Do I have such abilities in the new version?

YanaFloryanovich avatar Aug 24 '21 10:08 YanaFloryanovich

@JoshClose It is any function allow us to get collection of headers in the specified order (as defined in model) and compare it with the used csv file or this abilities separately?

YanaFloryanovich avatar Aug 24 '21 10:08 YanaFloryanovich

I think this is already being done for you...

The check for headers matching your model/attributes/map happens for you and then calls the HeaderValidated function. The default for this is to throw an exception saying what headers it found to be invalid. You can specify your own function, like you did, to either ignore the invalid headers or do something like log a message and rethrow. The args parameter has an InvalidHeaders[] property on it that gives the list of names and the index.

You can take a look at the header validation code here.

https://github.com/JoshClose/CsvHelper/blob/808dea2456b9c695eed1c124f67a2385e88b8a81/src/CsvHelper/CsvReader.cs#L129

JoshClose avatar Aug 24 '21 14:08 JoshClose

I think maybe the issue is that Yana would like to make sure the header names are all there and they are in the correct order. Right now you can do one or the other. You can map the headers by name, but they could be in any order or you can map the headers by index, but they could be any name.

AltruCoder avatar Aug 24 '21 15:08 AltruCoder

@JoshClose I need not only validation of missed or incorrect header, but and the right specified order.

YanaFloryanovich avatar Aug 24 '21 16:08 YanaFloryanovich

  var csvConfig = new CsvConfig { ValidateHeaderColumnOrder = true };
  
 // in CsvConfig

       public bool ValidateHeaderColumnOrder
    {
        get => _validateHeaderColumnOrder;
        set
        {
            _validateHeaderColumnOrder = value;
            if (value)
            {
                AddHeaderColumnOrderValidation();
            }
        }
    }
    
        private void AddHeaderColumnOrderValidation()
    {
        HeaderValidated = (invalidHeaders, context) =>
            {
                // Represent headers from file
                var cashedHeaderNames = context.NamedIndexCache.Values.Select(x => x.Item1);

                // Represent headers from model
                var headerNames = context.NamedIndexes.Keys;

                var areHeadersEqual = headerNames.SequenceEqual(cashedHeaderNames);
                if (!areHeadersEqual)
                {
                    throw new CsvManagerException(ReportResource.WrongCsvHeaderColumnOrderExceptionMessage);
                }
            };
    }

YanaFloryanovich avatar Aug 24 '21 16:08 YanaFloryanovich

Are you specifying the index for each property in either attributes or a class map?

JoshClose avatar Aug 24 '21 18:08 JoshClose

I have custom attributes which contains property for order. During class map creation I use this attribute using reflection. I use DefaultClassMap and specify MemberMap with ordering index. image If I can't use old approach is the other way to do such validation?

YanaFloryanovich avatar Aug 26 '21 13:08 YanaFloryanovich

If you're using attributes already, is there a reason you don't use the attributes included with CsvHelper and just not use a class map?

I'll have to think if there is a good way to accomplish the check you need. Those caches weren't meant to be used like that, or even be used at all externally.

JoshClose avatar Aug 26 '21 18:08 JoshClose