-
-
Notifications
You must be signed in to change notification settings - Fork 0
CsvCoreReader
The CsvCoreReader lets you read CSV files using a strongly typed approach, supports header mapping, custom delimiters, and data validation.
There are two ways to use the CsvCoreReader:
-
Constructor Injection: You can use the
CsvCoreReaderdirectly by passing theICsvCoreReaderinterface as parameter into the constructor. - Initialize: Create an instance of the reader and use this (not preffered!).
Csv files are based on a delimiter, normally you can depend on the system settings for the delimiter.
In case you need to use a different delimiter, you can use the UseDelimiter method to set a custom delimiter.
| Description | |
|---|---|
| Parameters | char |
| Returns | void |
| Usage | csvCoreReader.UseDelimiter(';') |
Example: Using a custom delimiter
var results = csvCoreReader
.UseDelimiter(';')
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
When you receive a CSV file without a header record, we need to know about this. By default, we will assume that the first record is a header record. So if not tell us, and we will read the file without a header record.
| Description | |
|---|---|
| Parameters | |
| Returns | void |
| Usage | csvCoreReader.WithoutHeader() |
Example: Reading without a header record
csv
Foo;Bar;01/01/2025;foo@bar.com
csharp
var results = csvCoreReader
.WithoutHeader()
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
By default, CsvCoreReader won't validate your data. We read your data, add it to a list of your result model and we are done.
Any validation with that result you can do it on your own, you know best what to do with it.
But if you want us to validate the data in the CSV file and only add success records to the list of result models you can.
If you want the error file to be stored in the same location as the application is running, you can use the Validate method without any parameters.
If you want to store the error file in a different location, you can use the Validate method with a string parameter.
| Description | |
|---|---|
| Parameters | optional path were to store the error file |
| Returns | void |
| Usage | csvCoreReader.Validate() |
Example: Enable validation, without a custom error path
csharp
var result = csvCoreReader
.Validate()
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
Example: Enable validation, with a custom error path
csharp
var result = csvCoreReader
.Validate(@"C:\Temp\Errors")
.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv"));
If you have a dateonly or datetime property in your model, and the csv file contains a date in a different format than the system settings,
you can use the SetDateTimeFormat method to set the format of the date.
| Description | |
|---|---|
| Parameters | string the date (or datetime) format |
| Returns | void |
| Usage | csvCoreReader.SetDateTimeFormat() |
Example: Set the date format in yearmonthday format
csv
Name;Surname;Birthdate;Email
Foo;Bar;20250726;foo@bar.com
csharp
var result = csvCoreReader
.SetDateTimeFormat("yyyyMMdd")
.Read<PersonCreatedModel>(Path.Combine("AnyPath", "YourFile.csv"));
The most basic use of the reader is to use constructor injection, use the field to call the Read or ReadAsync method with a model to add your csv data.
When calling the .Read<Model>(fullpathtoyourcsvfile), we will read the csv file for you and convert all lines into records of your specified type.
As told earlier, by default we won't validate your data, see the validation chapter in this wiki. If you have specified a non-nullable dateonly / datetime property in your model, and the csv file contains a null value for that property, the reader will set these properties to their MinValues.
| Description | |
|---|---|
| Parameters | string the full path to the csv |
| Returns | IEnumerable<T> |
| Usage | csvCoreReader.Read<ResultModel>(Path.Combine("AnyPath", "YourFile.csv")) |
| Async Usage | await csvCoreReader.ReadAsync<ResultModel>(Path.Combine("AnyPath", "YourFile.csv")) |
Example: Reads the csv file and converts it to a list of your model
csv
Name;Surname;Birthdate;Email
Foo;Bar;01/01/2025;foo@bar.com
csharp
public class ResultModel
{
public string Name { get; set; }
public string Surname { get; set; }
public string Birthdate { get; set; }
public string Email { get; set; }
}
csharp
var result = csvCoreReader
.Read<PersonModel>(Path.Combine("AnyPath", "YourFile.csv"));
Example: Reads the csv file asynchronized and converts it to a list of your model
csharp
var result = await csvCoreReader
.ReadAsync<PersonModel>(Path.Combine("AnyPath", "YourFile.csv"));
This is an experimental feature, we thought how about reading the csv file and insert those records directly into a database table. So lets do a little experiment. We only support Entity Framework for now just to see how things work out.
When you want to read the csv file and insert those records directly in a table, tell us what your databasecontext is by using this method.
| Description | |
|---|---|
| Parameters | DbContext |
| Returns | void |
| Usage | csvCoreReader.UseDbContext(yourDbContext) |
Example: Setting the database context
var dbContext = new YourDbContext();
await reader
.UseDbContext(dbContext)
.Persist<Employee>(Path.Combine("AnyPath", "YourFile.csv"));
When you set the DbContext by using the UseDbContext, you now can call the Persist or the PersistAsync method on the reader.
Provide the entity that stores the records and let CsvCore do the rest.
Again its an experimental feature, we only support adding new records. If the table is empty we insert all records directly into the table. If there are already some records in it we will figure out which one to add and which one we skip.
| Description | |
|---|---|
| Parameters | DbContext |
| Returns | void |
| Usage | csvCoreReader.Persist<Entity>(Path.Combine("AnyPath", "YourFile.csv")) |
| Async Usage | await csvCoreReader.PersistAsync<Entity>(Path.Combine("AnyPath", "YourFile.csv")) |
Example: Setting the database context and persist the result into the table
var dbContext = new YourDbContext();
reader
.UseDbContext(dbContext)
.Persist<Employee>(Path.Combine("AnyPath", "YourFile.csv"));
Example: Setting the database context and persist the result asynchronized into the table
var dbContext = new YourDbContext();
reader
.UseDbContext(dbContext)
.Persist<Employee>(Path.Combine("AnyPath", "YourFile.csv"));
In the most ideal world the content of the csv file will match the target model. If that is the case simply create a class (model) that will match the csv content.
Example: Result model that matches the csv content
csv
Name;Surname;Birthdate;Email
Foo;Bar;01/01/2025;foo@bar.com
csharp
public class ResultModel
{
public string Name { get; set; }
public string Surname { get; set; }
public string Birthdate { get; set; }
public string Email { get; set; }
}
Sometimes, in my experience always, you'll receive a csv were the column order does not match the order in your result model.
For those situations we created the [Header] attribute.
When the columns in your csv don't match the model's order, use the [Header(position)]:
Example: Set the column index on the correct property
csv
Surname;Name;Birthdate;Email
Bar;Foo;01/01/2025;foo@bar.com
csharp
public class NotMatchingPersonModel
{
[Header(2)]
public string Name { get; set; }
[Header(1)]
public string Surname { get; set; }
[Header(3)]
public DateOnly BirthDate { get; set; }
[Header(4)]
public string Email { get; set; }
}
It can happen that you receive a csv file were the column names in the header record are different then the property names in your model.
This is were the header attribute will come to the rescue again.
When the column names in your csv don't match the model's property names, use the [Header(position, name)]:
Example: Set the column name on the correct property
csv
First_Name;Family_Name;Date_Of_Birth;Contact_Email
Foo;Bar;01/01/2025;foo@bar.com
csharp
public class PersonCustomNames
{
[Header(1, "First_Name")]
public string Name { get; set; }
[Header(2, "Family_Name")]
public string Surname { get; set; }
[Header(3, "Date_Of_Birth")]
public DateOnly BirthDate { get; set; }
[Header(4, "Contact_Email")]
public string Email { get; set; }
}