Skip to content

Commit 1629a97

Browse files
DotNet2WebTino Klijn
andauthored
40 not all required fields in result model using read validation are be considered (#44)
* Add all missing field in error file. * Handling Enums * even if the result is filled with lots of data but the result model only have a few properties it still should map it. * Always skip validation, only validate when beeing asked to. --------- Co-authored-by: Tino Klijn <tino@dotnet2web.nl>
1 parent fd0d5d9 commit 1629a97

File tree

6 files changed

+89
-27
lines changed

6 files changed

+89
-27
lines changed

CsvCore.Specs/CsvCoreReaderSpecs.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ public void
547547
var result = csvCoreReader
548548
.UseDelimiter(';')
549549
.WithoutHeader()
550+
.Validate()
550551
.Read<ZeroBasedNotMatchingPersonModel>(filePath);
551552

552553
// Assert
@@ -615,6 +616,7 @@ public void Should_Validate_The_Input_When_Reading_The_Csv_File()
615616

616617
// Act
617618
var result = csvCoreReader
619+
.Validate()
618620
.Read<PersonModel>(filePath).ToList();
619621

620622
// Assert
@@ -669,6 +671,7 @@ public void Should_Write_An_ErrorFile_Without_Using_The_WriteErrorsAt_Method()
669671

670672
// Act
671673
var result = csvCoreReader
674+
.Validate()
672675
.Read<PersonModel>(filePath).ToList();
673676

674677
// Assert
@@ -732,6 +735,7 @@ public void Should_Validate_The_Input_When_Reading_The_Csv_File_And_Write_An_Err
732735
// Act
733736
var result = csvCoreReader
734737
.SetErrorPath(errorLocation)
738+
.Validate()
735739
.Read<PersonModel>(filePath).ToList();
736740

737741
// Assert
@@ -877,7 +881,6 @@ public void Should_Generate_A_Full_Model_With_Invalid_Records_When_Reading_The_C
877881

878882
// Act
879883
var result = csvCoreReader
880-
.SkipValidation()
881884
.Read<PersonModel>(filePath).ToList();
882885

883886
// Assert
@@ -1063,6 +1066,7 @@ public void Should_Add_All_Missing_Required_Fields_Into_Error_File_When_Data_Is_
10631066
// Act
10641067
var result = csvCoreReader
10651068
.UseDelimiter(';')
1069+
.Validate()
10661070
.Read<CarResultModel>(filePath);
10671071

10681072
// Assert
@@ -1094,4 +1098,48 @@ public void Should_Add_All_Missing_Required_Fields_Into_Error_File_When_Data_Is_
10941098
// Cleanup
10951099
FileHelper.DeleteTestFile(filePath);
10961100
}
1101+
1102+
[Fact]
1103+
public void Should_Read_Provided_Csv_File_When_The_Result_Model_Contains_Only_A_Set_Of_Properties()
1104+
{
1105+
// Arrange
1106+
var csvCoreReader = new CsvCoreReader();
1107+
var directory = Directory.GetCurrentDirectory();
1108+
1109+
var filePath = Path.Combine(directory, new Faker().System.FileName(CsvExtension));
1110+
1111+
File.Create(filePath).Dispose();
1112+
1113+
var cars = new Faker<CsvCarContentModel>()
1114+
.RuleFor(c => c.Id, faker => faker.Vehicle.Random.Guid().ToString())
1115+
.RuleFor(c => c.Manufacturer, faker => faker.Vehicle.Manufacturer().ToString())
1116+
.RuleFor(c => c.Model, faker => faker.Vehicle.Model().ToString())
1117+
.RuleFor(c => c.Vin, faker => faker.Vehicle.Vin().ToString())
1118+
.RuleFor(c => c.YearOfConstruction, faker => faker.Date.Past().Year.ToString())
1119+
.RuleFor(c => c.Mileage, faker => faker.Vehicle.Random.Int(0, 100_000).ToString())
1120+
.RuleFor(c => c.Fuel, faker => faker.Random.Int(0, 3).ToString())
1121+
.Generate(1);
1122+
1123+
var csvCoreWriter = new CsvCoreWriter();
1124+
csvCoreWriter
1125+
.UseDelimiter(';')
1126+
.Write(filePath, cars);
1127+
1128+
// Act
1129+
var result = csvCoreReader
1130+
.UseDelimiter(';')
1131+
.Read<CarWithOnlyAFewColumnsSelectedModel>(filePath);
1132+
1133+
// Assert
1134+
var convertedCar = result.ToList();
1135+
convertedCar.Count.Should().Be(1);
1136+
1137+
convertedCar.First().Id.Should().Be(cars[0].Id);
1138+
convertedCar.First().Manufacturer.Should().Be(cars[0].Manufacturer);
1139+
convertedCar.First().Model.Should().Be(cars[0].Model);
1140+
convertedCar.First().Mileage.Should().Be(int.Parse(cars[0].Mileage));
1141+
1142+
// Cleanup
1143+
FileHelper.DeleteTestFile(filePath);
1144+
}
10971145
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System;
2+
3+
namespace CsvCore.Specs.Models;
4+
5+
public class CarWithOnlyAFewColumnsSelectedModel
6+
{
7+
public Guid Id { get; set; }
8+
9+
public string Manufacturer { get; set; }
10+
11+
public string Model { get; set; }
12+
13+
public int Mileage { get; set; }
14+
}

CsvCore/Documentation/CsvCoreReader.md

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,27 @@ When you have the model all setup use the `CsvCoreReader` to read the csv file,
8484

8585
### Validations
8686

87-
Ofcourse you will receive csv files that are not valid, so we added some validations to the reader.
87+
Ofcourse you will receive csv files that are not valid.
8888

89-
We will validate the data before adding them to the result models, any record that cant be parsed correctly will be added to errors.csv file.
89+
By default `CsvCoreReader` won't validate the data, it just reads the csv file and maps the data to your model.
90+
If you want `CsvCoreReader` to validate the data, you can use the `Validate` method.
9091

91-
The file will be stored at the location your application will be run. The filename will be the same as the original file, but we just add `_errors` to it.
92+
### Example
93+
94+
```csharp
95+
var result = csvCoreReader
96+
.Validate()
97+
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
98+
```
99+
100+
This will validate the data before it adds the line into the result model. If the data is not valid, it will be added to the errors.csv file.
101+
The reader will return a list with valid objects and the errors will be written to the errors.csv file as described in the next section.
102+
103+
**A little note:**
104+
- _If you have a non-nullable dateonly / datetime property in your model, and the csv file contains a null value, the reader will set these properties to their MinValues._
105+
106+
When using the `Validate` method, the reader will create a file called `<originalfilename>_errors.csv` in the same location as your application is run.
107+
The filename will be the same as the original file, but we just add `_errors.csv` to it.
92108

93109
If you need those error files to be written somewhere else simply use the `.SetErrorPath("AnyPath")` method on the reader
94110

@@ -126,20 +142,3 @@ The `IsValid` method will return a `List<ValidationModel>` containing:
126142
- The reason why the data could not be parsed stored in the error message property
127143

128144
This could be handy in numerous ways.
129-
130-
And how about skipping the validation. If you want to skip the validation, you can use the `SkipValidation` method.
131-
### Example
132-
133-
```csharp
134-
var result = csvCoreReader
135-
.SkipValidation()
136-
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
137-
```
138-
139-
This will skip the validation and read the csv file without validating the data.
140-
The result will be a list of `ResultModel` objects, but the data will not be validated.
141-
142-
**A little note about the validation:**
143-
- _If you have a non-nullable dateonly / datetime property in your model, and the csv file contains a null value, the reader will set these properties to their MinValues._
144-
145-
This way you can do whatever you want with the result.

CsvCore/Documentation/CsvCoreWriter.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public class PersonModel
2121

2222
public string Email { get; set; }
2323
}
24+
```
2425

2526
```csharp
2627
public class Foo(ICsvCoreWriter csvCoreWriter)

CsvCore/Reader/CsvCoreReader.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class CsvCoreReader : ICsvCoreReader
1414
private string? delimiter;
1515
private bool hasHeaderRecord = true;
1616
private string errorFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Errors");
17-
private bool skipValidation;
17+
private bool validate;
1818
private string? dateTimeFormat;
1919

2020
/// <summary>
@@ -69,9 +69,9 @@ public CsvCoreReader SetDateTimeFormat(string format)
6969
/// Use this method to tell us that the CSV file does not have a header record.
7070
/// </summary>
7171
/// <returns></returns>
72-
public CsvCoreReader SkipValidation()
72+
public CsvCoreReader Validate()
7373
{
74-
skipValidation = true;
74+
validate = true;
7575
return this;
7676
}
7777

@@ -232,7 +232,7 @@ private IEnumerable<ValidationModel> GenerateModelBasedOnHeader<T>(List<string>
232232
continue;
233233
}
234234

235-
if (!skipValidation)
235+
if (validate)
236236
{
237237
var validationResult = validationHelper.Validate(record[i], property, rowNumber, dateTimeFormat);
238238

@@ -279,7 +279,7 @@ private IEnumerable<ValidationModel> GenerateModel<T>(string[] record, T target,
279279

280280
var index = DetermineIndex(property, startPosition, i);
281281

282-
if (!skipValidation)
282+
if (validate)
283283
{
284284
var validationResult = validationHelper.Validate(record[index], property, rowNumber, dateTimeFormat);
285285

CsvCore/Reader/ICsvCoreReader.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public interface ICsvCoreReader
1010

1111
CsvCoreReader SetDateTimeFormat(string format);
1212

13-
CsvCoreReader SkipValidation();
13+
CsvCoreReader Validate();
1414

1515
IEnumerable<T> Read<T>(string filePath) where T : class;
1616
}

0 commit comments

Comments
 (0)