Can't find NamedIndexCache and NamedIndexes
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?
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.
HeaderValidated = args => { var cashedHeaderNames = args.Context.NamedIndexCache.Values.Select(x => x.Item1); var headerNames = args.Context.NamedIndexes.Keys; var areHeadersEqual = headerNames.SequenceEqual(cashedHeaderNames); };
What are you using areHeadersEqual for? Maybe we can accomplish the same thing in another way.
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");
}
};
Are you doing multiple files in a row and want to know if a file has a different column order?
@JoshClose If I am not mistaken, it just checks ordering in single file.
Let me check it properly.
@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?
@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?
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
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.
@JoshClose I need not only validation of missed or incorrect header, but and the right specified order.
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);
}
};
}
Are you specifying the index for each property in either attributes or a class map?
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.
If I can't use old approach is the other way to do such validation?
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.