Banner

One of my favorite tricks for data-driven apps is to include sample data during development. This sample data is invaluable for various purposes such as designing UIs, conducting demos, or running tests.

For this reason, I recommend integrating test data into the solution for debug releases. While not suitable for release builds, it proves highly beneficial during debug mode.

Getting Started

First, obtain a sample dataset. For instance, you can use the Titanic dataset available here.

Next, add the CSV file to your file structure. Your Solution Explorer should resemble the following:

Solution Explorer

Particularly important, don’t forget to change the property Build Action to Embedded resource. Otherwise, this is not working.

Embedded Resources File

Code

Create a class to represent TitanicPassengers:

using System.ComponentModel.DataAnnotations;

namespace Common.Models;

public class TitanicPassenger
{
    [Key]
    public int PassengerId { get; set; }
    public bool Survived { get; set; }
    public int Pclass { get; set; }
    [Required]
    public string Sex { get; set; }
    public float Age { get; set; }
    [Required]
    public string Name { get; set; }
    public int SibSp { get; set; }
    public int Parch { get; set; }
    [Required]
    public string Ticket { get; set; }
    public float Fare { get; set; }
    [Required]
    public string Cabin { get; set; }
    public char Embarked { get; set; }
}

Use the following code to read data from the embedded file:

using Common;
using Common.Models;
using System.Reflection;

namespace DataWebApp.Models;

public class TitanicPassengersSeed
{
    // Load CSV file into a List of TitanicPassenger   
    public static List<TitanicPassenger> LoadPassengers()
    {
        // Get the file from embedded resources
        Assembly assembly = Assembly.GetExecutingAssembly();
        string resourceName = "Common.SampleData.TitanicPassengers.csv";
        Stream? stream = assembly.GetManifestResourceStream(resourceName);
        if (stream == null)
        {
            throw new Exception("Cannot find TitanicPassengers.csv");
        }
        StreamReader reader = new StreamReader(stream);
        string[] lines = reader.ReadToEnd().Split('\n');
        List<TitanicPassenger> passengers = new();

        // Read file and create TitanicPassenger objects
        foreach (var line in lines.Skip(1))
        {
            // The Names of the passengers have commas
            // so we need to replace ", " with "__ " to avoid splitting the name
            string lineHelper = line.Replace(", ", "__ ");
            string[] columns = lineHelper.Split(',');
            TitanicPassenger passenger = new()
            {
                Survived = columns[1] == "1",
                Pclass = int.Parse(columns[2]),
                Name = columns[3].Replace("__ ", ", ").Replace("\"", ""),
                Sex = columns[4],
                Age = float.Parse(string.IsNullOrEmpty(columns[5]) ? "0" : columns[5]),
                SibSp = int.Parse(string.IsNullOrEmpty(columns[6]) ? "0" : columns[6]),
                Parch = int.Parse(string.IsNullOrEmpty(columns[7]) ? "0" : columns[7]),
                Ticket = columns[8],
                Fare = float.Parse(string.IsNullOrEmpty(columns[9]) ? "0" : columns[9]),
                Cabin = columns[10],
                Embarked = columns[11][0]
            };
            passengers.Add(passenger);
        }
        return passengers;
    }

    // Seed the database with the List of TitanicPassenger
    public static void SeedPassengers(MyCopilotDbContext context)
    {
        if (context.TitanicPassengers.Any())
        {
            return;   // DB has been seeded
        }
        List<TitanicPassenger> passengers = LoadPassengers();
        context.TitanicPassengers.AddRange(passengers);
        context.SaveChanges();
    }
}

Conclusion

With this approach, you can easily load seed data into your database for testing purposes.

Happy coding!