Migration
+Migration steps for major version bumps.
+ + +diff --git a/docs/migration/index.html b/docs/migration/index.html new file mode 100644 index 000000000..03ee81b34 --- /dev/null +++ b/docs/migration/index.html @@ -0,0 +1,131 @@ + + +
+ + + + + + + + + + + + + + + + + + + +Migration steps for major version bumps.
+ + +ConvertUsing
was renamed to Convert
.
// v19
+Map(m => m.Property).ConvertUsing(row => row.GetField<int>(0) + row.GetField<int>(1));
+
+// v20
+Map(m => m.Property).Convert(row => row.GetField<int>(0) + row.GetField<int>(1));
+
+All properties changed from get; set;
to get; init;
.
// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture);
+config.Delimiter = ";";
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ Delimiter = ";",
+}
+
+CsvConfiguration
changed from a class
to a record
.
// v19
+class MyConfig : CsvConfiguration {}
+
+// v20
+record MyConfig : CsvConfiguration {}
+
+ShouldQuote
now takes in IWriterRow
instead of CsvContext
.
// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = (field, row) => true,
+};
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = (field, context) => true,
+};
+
+Changed from enum NewLines
to char?
.
// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ NewLine = NewLines.LF,
+};
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ NewLine = '\n',
+};
+
+This was removed. Any code referencing this should be deleted.
+This moved to CsvContext
.
// v19
+csv.Configuration.RegisterClassMap<MyMap>();
+
+// v20
+csv.Context.RegisterClassMap<MyMap>();
+
+This moved to CsvContext
.
// v19
+csv.Configuration.UnregisterClassMap<MyMap>();
+
+// v20
+csv.Context.UnregisterClassMap<MyMap>();
+
+This moved to CsvContext
.
// v19
+csv.Configuration.AutoMap<MyType>();
+
+// v20
+csv.Context.AutoMap<MyType>();
+
+All setters removed.
+// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture);
+config.Delimiter = ";";
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ Delimiter = ";",
+};
+
+bool CacheFields
.bool LeaveOpen
.char? NewLine
.ParserMode Mode
.char[] WhiteSpaceChars
.bool IgnoreQuotes
.Any classes that implement IParserConfiguration
will need these changes.
All setters removed.
+// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture);
+config.Delimiter = ";";
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ Delimiter = ";",
+};
+
+TypeConverterOptionsCache
.TypeConverterCache
.Maps
.RegisterClassMap
.UnregisterClassMap
.AutoMap
.Any classes that implement IReaderConfiguration
will need these changes.
This interface was removed and it's properties were added to IWriteConfiguration
.
// v19
+class MyConfig : ISerializerConfiguration {}
+
+// v20
+class MyConfig : IWriterConfiguration {}
+
+All setters removed.
+// v19
+var config = new CsvConfiguration(CultureInfo.InvariantCulture);
+config.Delimiter = ";";
+
+// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ Delimiter = ";",
+};
+
+QuoteString
.TypeConverterCache
.MemberTypes
.Maps
.RegisterClassMap
.UnregisterClassMap
.AutoMap
.Any classes that implement IWriterConfiguration
will need these changes.
ConvertUsing
renamed to Convert
.
// v19
+Map(m => m.Property).ConvertUsing(row => row.Get(0));
+Map(m => m.Property).ConvertUsing(value => value?.ToString() ?? string.Empty);
+
+// v20
+Map(m => m.Property).Convert(row => row.Get(0));
+Map(m => m.Property).Convert(value => value?.ToString() ?? string.Empty);
+
+string[] Read()
changed to bool Read()
.
// v19
+string[] record;
+while ((record = parser.Read()) != null)
+{
+}
+
+// v20
+while (parser.Read())
+{
+ // Only get fields you need.
+ var field1 = parser[0];
+ var field2 = parser[1];
+
+ // Get all fields.
+ var record = parser.Record;
+}
+
+Constructor paramter IFieldReader fieldReader
removed from all constructors.
// v19
+var parser = new CsvParser(fieldReader);
+
+// v20
+var parser = new CsvParser();
+
+Removed. Functionality moved into CsvWriter
.
Removed. Functionality moved into CsvParser
.
long ByteCount
.long CharCount
.int Count
.string this[int index]
.string[] Record
.string RawRecord
.int Row
.int RawRow
.string[] Read
to bool Read
.Task<string[]> ReadAsync
to Task<bool> ReadAsync
.Any classes that implement IParser
will need these changes.
ICsvParser Parser
.Any classes that implement IReader
will need these changes.
int ColumnCount
.int CurrentIndex
.string[] HeaderRecord
.IParser Parser
.Any classes that implement IReaderRow
will need these changes.
Removed. Functionality moved into IWriter
.
string[] HeaderRecord
.int Row
.int Index
.Removed. Functionality moved into CsvWriter
.
enum Caches
was removed. Modifying internal caches is not supported anymore.
+Any code referencing this should be removed.
ReadingContext
and WritingContext
was merged into a single CsvContext
.
+Anywhere either of these was used should change to CsvContext
.
Any place a Func
or Action
was used now has a dedicated delegate
.
+This should only affect classes that are inheriting ClassMap
+or CsvConfiguration
.
Class removed. Code was wrapped into CsvParser
.
Property char? NewLine
changed to string NewLine
.
// v20
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ NewLine = '\r',
+};
+
+// v21
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ NewLine = "\r",
+};
+
+
+ Name change to CsvMode
.
// v21
+ParserMode.RFC4180
+
+//v22
+CsvMode.RFC4180
+
+// v21
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = (field, context) => true,
+};
+
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = (field, context, row) => true,
+};
+
+EnumConverter
was changed to case sensitive by default.
If you want Enums to ignore case, you need to set a type converter option.
+Map(m => m.Property).TypeConverterOption.EnumIgnoreCase();
+
+ProcessFieldBufferSizse
.Any class that implements IParserConfiguration
will need these changes applied to it.
Mode
.Any class that implements IWriterConfiguration
will need these changes applied to it.
All the constructor parameters were removed in favor of using +property setters. Apply this change to any of the options.
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture, delimiter = ";");
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ Delimiter = ";",
+};
+
+All delegates now take in a single struct argument.
+BadDataFound
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ BadDataFound = (field, context) =>
+ {
+ Console.WriteLine($"field: {field}");
+ Console.WriteLine($"context: {context}");
+ },
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ BadDataFound = args =>
+ {
+ Console.WriteLine($"field: {args.Field}");
+ Console.WriteLine($"context: {args.Context}");
+ },
+};
+
+ConvertFromString
+// v22
+Map(m => m.Property).Convert(row => row.GetField(0));
+
+// v23
+Map(m => m.Property).Convert(args => args.Row.GetField(0));
+
+ConvertToString
+// v22
+Map(m => m.Property).Convert(value => value.ToString());
+
+// v23
+Map(m => m.Property).Convert(args => args.Value.ToString());
+
+GetConstructor
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ GetConstructor = classType => classType.GetConstructors().First(),
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ GetConstructor = args => args.ClassType.GetConstructors().First(),
+};
+
+GetDynamicPropertyName
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ GetDynamicPropertyName = (fieldIndex, context) => $"Field{fieldIndex}";
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ GetDynamicPropertyName = args => $"Field{args.FieldIndex}",
+};
+
+HeaderValidated
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ HeaderValidated = (invalidHeaders, context) => Console.WriteLine($"Invalid headers count: {invalidHeaders.Count}"),
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ HeaderValidated = args => Console.WriteLine($"Invalid headers count: {args.InvalidHeaders.Count}"),
+};
+
+MissingFieldFound
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ MissingFieldFound = (headerNames, index, context) => Console.WriteLine($"Missing field: {headerNames[0]}"),
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ MissingFieldFound = args => Console.WriteLine($"Missing field: {args.HeaderNames[0]}"),
+};
+
+PrepareHeaderForMatch
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ PrepareHeaderForMatch = (header, fieldIndex) => header.ToLower(),
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ PrepareHeaderForMatch = args => args.Header.ToLower(),
+};
+
+ReadingExceptionOccurred
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ReadingExceptionOccurred = exception =>
+ {
+ Console.WriteLine(exception.Message);
+ throw args.Exception;
+ },
+};
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ReadingExceptionOccurred = args =>
+ {
+ Console.WriteLine(args.Exception.Message);
+ throw args.Exception;
+ },
+};
+
+ReferenceHeaderPrefix
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ReferenceHeaderPrefix = (memberType, memberName) => $"{memberName}.",
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ReferenceHeaderPrefix = args => $"{args.MemberName}.",
+};
+
+ShouldQuote
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = (field, fieldType, row) => true,
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldQuote = args => true,
+};
+
+ShouldSkipRecord
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldSkipRecord = (records) => record.Length == 0,
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldSkipRecord = args => args.Record.Length == 0,
+};
+
+ShouldUseConstructorParameters
+// v22
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldUseConstructorParameters = type => true;
+};
+
+// v23
+var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ ShouldUseConstructorParameters = args => true;
+};
+
+Validate
+// v22
+Map(m => m.Property).Validate(field => !string.IsNullOrEmpty(field));
+
+// v23
+Map(m => m.Property).Validate(args => !string.IsNullOrEmpty(args.Field));
+
+
+ // v23
+WriteConvertedField(field);
+
+// v24
+WriteConvertedField(field, fieldType);
+
+// v23
+WriteConvertedField(field);
+
+// v24
+WriteConvertedField(field, fieldType);
+
+
+ All delegate args had their non-parameterless constructor removed
+in favor of using init
.
BadDataFoundArgs
+// v25
+var args = new BadDataRoundArgs(field, rawRecord, context);
+
+// v26
+var args = new BadDataFoundArgs
+{
+ Field = field,
+ RawRecord = rawRecord,
+ Context = context,
+};
+
+ConvertFromStringArgs
+// v25
+var args = new ConvertFromStringArgs(row);
+
+// v26
+var args = new ConvertFromStringArgs
+{
+ Row = row,
+};
+
+ConvertToStringArgs
+// v25
+var args = new ConvertToStringArgs(value);
+
+// v26
+var args = new ConvertToStringArgs
+{
+ Value = value,
+};
+
+GetConstructorArgs
+// v25
+var args = new GetConstructorArgs(type);
+
+// v26
+var args = new GetConstructorArgs
+{
+ ClassType = type,
+};
+
+GetDynamicPropertyNameArgs
+// v25
+var args = new GetDynamicPropertyNameArgs(index, context);
+
+// v26
+var args = new GetDynamicPropertyNameArgs
+{
+ FieldIndex = index,
+ Context = context,
+};
+
+HeaderValidatedArgs
+// v25
+var args = new HeaderValidatedArgs(headers, context);
+
+// v26
+var args = new HeaderValidatedArgs
+{
+ InvalidHeaders = headers,
+ Context = context,
+};
+
+MissingFieldFoundArgs
+// v25
+var args = new MissingFieldFoundArgs(headerNames, index, context);
+
+// v26
+var args = new MissingFieldFoundArgs
+{
+ HeaderNames = headerNames,
+ Index = index,
+ Context = context,
+};
+
+PrepareHeaderForMatchArgs
+// v25
+var args = new PrepareHeaderForMatchArgs(header, fieldIndex);
+
+// v26
+var args = new PrepareHeaderForMatchArgs
+{
+ Header = header,
+ FieldIndex = fieldIndex,
+};
+
+ReadingExceptionOccurredArgs
+// v25
+var args = new ReadingExceptionOccurredArgs(exception);
+
+// v26
+var args = new ReadingExceptionOccurredArgs
+{
+ Exception = exception,
+};
+
+ReferenceHeaderPrefixArgs
+// v25
+var args = new ReferenceHeaderPrefixArgs(memberType, memberName);
+
+// v26
+var args = new ReferenceHeaderPrefixArgs
+{
+ MemberType = memberType,
+ MemberName = memberName,
+};
+
+ShouldQuoteArgs
+// v25
+var args = new ShouldQuoteArgs(field, fieldType, row);
+
+// v26
+var args = new ShouldQuoteArgs
+{
+ Field = field,
+ FieldType = fieldType,
+ Row = row,
+};
+
+ShouldSkipRecordArgs
+// v25
+var args = new ShouldSkipRecordArgs(record);
+
+// v26
+var args = new ShouldSkipRecordArgs
+{
+ Record = record,
+};
+
+ShouldUseConstructorParametersArgs
+// v25
+var args = new ShouldUseConstructorParametersArgs(parameterType);
+
+// v26
+var args = new ShouldUseConstructorParametersArgs
+{
+ ParameterType = parameterType,
+};
+
+ValidateArgs
+// v25
+var args = new ValidateArgs(field);
+
+// v26
+var args = new ValidateArgs
+{
+ Field = field,
+};
+
+
+ All delegates args objects have their init
accessor removed.
+Constructor parameters are used instead.
BadDataFoundArgs
+// v26
+var args = new BadDataFoundArgs
+{
+ Field = field,
+ RawRecord = rawRecord,
+ Context = context,
+};
+
+// v27
+var args = new BadDataRoundArgs(field, rawRecord, context);
+
+ConvertFromStringArgs
+// v26
+var args = new ConvertFromStringArgs
+{
+ Row = row,
+};
+
+// v27
+var args = new ConvertFromStringArgs(row);
+
+ConvertToStringArgs
+// v26
+var args = new ConvertToStringArgs
+{
+ Value = value,
+};
+
+// v27
+var args = new ConvertToStringArgs(value);
+
+GetConstructorArgs
+// v26
+var args = new GetConstructorArgs
+{
+ ClassType = type,
+};
+
+// v27
+var args = new GetConstructorArgs(type);
+
+GetDynamicPropertyNameArgs
+// v26
+var args = new GetDynamicPropertyNameArgs
+{
+ FieldIndex = index,
+ Context = context,
+};
+
+// v27
+var args = new GetDynamicPropertyNameArgs(index, context);
+
+HeaderValidatedArgs
+// v26
+var args = new HeaderValidatedArgs
+{
+ InvalidHeaders = headers,
+ Context = context,
+};
+
+// v27
+var args = new HeaderValidatedArgs(headers, context);
+
+MissingFieldFoundArgs
+// v26
+var args = new MissingFieldFoundArgs
+{
+ HeaderNames = headerNames,
+ Index = index,
+ Context = context,
+};
+
+// v27
+var args = new MissingFieldFoundArgs(headerNames, index, context);
+
+PrepareHeaderForMatchArgs
+// v26
+var args = new PrepareHeaderForMatchArgs
+{
+ Header = header,
+ FieldIndex = fieldIndex,
+};
+
+// v27
+var args = new PrepareHeaderForMatchArgs(header, fieldIndex);
+
+ReadingExceptionOccurredArgs
+// v26
+var args = new ReadingExceptionOccurredArgs
+{
+ Exception = exception,
+};
+
+// v27
+var args = new ReadingExceptionOccurredArgs(exception);
+
+ReferenceHeaderPrefixArgs
+// v26
+var args = new ReferenceHeaderPrefixArgs
+{
+ MemberType = memberType,
+ MemberName = memberName,
+};
+
+// v27
+var args = new ReferenceHeaderPrefixArgs(memberType, memberName);
+
+ShouldQuoteArgs
+// v26
+var args = new ShouldQuoteArgs
+{
+ Field = field,
+ FieldType = fieldType,
+ Row = row,
+};
+
+// v27
+var args = new ShouldQuoteArgs(field, fieldType, row);
+
+ShouldSkipRecordArgs
+// v26
+var args = new ShouldSkipRecordArgs
+{
+ Record = record,
+};
+
+// v27
+var args = new ShouldSkipRecordArgs(record);
+
+ShouldUseConstructorParametersArgs
+// v26
+var args = new ShouldUseConstructorParametersArgs
+{
+ ParameterType = parameterType,
+};
+
+// v27
+var args = new ShouldUseConstructorParametersArgs(parameterType);
+
+ValidateArgs
+// v26
+var args = new ValidateArgs
+{
+ Field = field,
+};
+
+// v27
+var args = new ValidateArgs(field);
+
+bool ExceptionMessagesContainRawData { get; }
.Any class that implements IParserConfiguration
will need these changes
+applied to it.
bool ExceptionMessagesContainRawData { get; }
.Any class that implements IParserConfiguration
will need these changes
+applied to it.
\t
from the array of default characters.If you are expecting \t
to be trimmed, you will need to add this to the
+whitespace characters.
var config = new CsvConfiguration(CultureInfo.InvariantCulture)
+{
+ WhiteSpaceCharacters = new[] { ' ', '\t' },
+};
+
+bool DetectDelimiter { get; }
.string[] DetectDelimiterValues { get; }
.Any class that implements IParserConfiguration
will need these changes
+applied to it.
Task WriteRecordsAsync<T>(IAsyncEnumerable<T> records, CancellationToken cancellationToken = default)
.
+This does not apply to projects that reference the net45
version of CsvHelper.Any class that implements IWriter
will need these changes applied to it.
string Delimiter { get; }
.Any class that implements IParser
will need these changes applied to it.