Skip to content

CsvCoreReader

DotNet2Web edited this page May 29, 2025 · 14 revisions

The CsvCoreReader lets you read CSV files using a strongly typed approach, supports header mapping, custom delimiters, and data validation.

Usage

There are two ways to use the CsvCoreReader:

  1. Constructor Injection: You can use the CsvCoreReader directly by passing the ICsvCoreReader interface as parameter into the constructor.
  2. Initialize: Create an instance of the reader and use this (not preffered!).

Methods

UseDelimiter

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"));

WithoutHeader

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")); 

Validate

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"));

SetDateTimeFormat

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"));

Read / ReadAsync

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"));

UseDbContext

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"));

Persist / PersistAsync

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"));

Mapping

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; }
}

Mapping with the Header attribute position

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; }
}

Mapping with the Header attribute position and different column names

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; }
}