Bogus custom Dataset
Published: 2024-01-06 22:21:29

## Introduction

[Bogus](https://github.com/bchavez/Bogus) NuGet [package](https://www.nuget.org/packages/Bogus) is fake data generator which can be helpful for populating tables in a database and testing purposes. If a database is not used and Bogus populates list of data each time an application runs, the data is random, never the same. Also, the random data generated by Bogus may not meet a developer’s requirements.

For this reason, Bogus can be extended with a DataSet. Normal use of a DataSet is to set the locale for data generation but in this article learn how to use a Bogus DataSet to use realistic data.

The model will be three tables from a modified Microsoft NorthWind database (script is included in source code), Category, Contact and ContactType.


![demonstration screen shot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/va7kfpj3vjaul4iy69ub.png)

## Steps to create a custom DataSet

Create the models which match tables in NorthWind database.

```csharp
public class Categories
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }
    public byte[] Photo { get; set; }
    public Bitmap Picture { get; set; }
}

public class Contact
{
    public int ContactId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int ContactTypeIdentifier { get; set; }
    public ContactType ContactType { get; set; } = new();
    public override string ToString() => $"{FirstName} {LastName}";
    
    public Contact(int id)
    {
        ContactId = id;
    }

    public Contact()
    {

    }

}

public class ContactType
{
    public int ContactTypeIdentifier { get; set; }
    public string ContactTitle { get; set; }
    public override string ToString() => ContactTitle;

}
```

Next, read data from the database into json strings. Recommend using Microsoft Visual Studio Code with [SQL Server (mssql) extension](https://marketplace.visualstudio.com/items?itemName=ms-mssql.mssql) (free) which a SELECT statement can be exported to a json file. Once exported, paste the json into a method. In this case view BogusNorthWindLibrary.Classes.JsonStatements methods which stored json in raw string literals.

Next create a class which inherits Bogus DataSet as shown below.

Each method reads data from the json discussed prior. 

> **Note**
> Do not overthink performance here.


```csharp
public class NorthWind : DataSet
{

    private static Categories RandomCategory 
        => System.Random.Shared.GetItems(categories()!.ToArray(), 1)[0];

 
    public static Categories SingleCategory() 
        => RandomCategory;

    private static List<Categories>? categories()
    {
        List<Categories>? list = JsonSerializer
            .Deserialize<List<Categories>>(JsonStatements.CategoriesData);

        foreach (var cat in list!)
        {
            cat.Picture = cat.Photo.ByteToImage();
        }

        return list;
    }

    public static ContactType GetContactType(int id) 
        => JsonSerializer.Deserialize<List<ContactType>>(JsonStatements.ContactTypeData)!
            .FirstOrDefault(x => x.ContactTypeIdentifier == id)!;

    public static Contact SingleContact()
    {
        var contact = System.Random.Shared.GetItems(JsonSerializer
            .Deserialize<List<Contact>>(JsonStatements.ContactData)!.ToArray(), 1)[0];
        var contactType = GetContactType(contact.ContactTypeIdentifier);
        contact.ContactType = contactType;

        return contact;
    }
}
```

## Usage

We need a Contact with a ContactType

```csharp
Contact contact = NorthWind.SingleContact();
```

A Category is needeed.

```csharp
Categories category = NorthWind.SingleCategory();
```

## Integration into a create Faker

First thing required is an extension method

```csharp
public static class BogusExtensions
{
    /// <summary>
    /// Entry point for faker RuleFor
    /// </summary>
    public static NorthWind NorthWind(this Faker faker) 
        => ContextHelper.GetOrSet(faker, () => new NorthWind());
}
``` 
Setup static data and note the contact titles could be obtained from extraction from the json data used prior.

```csharp
private static string[] contactTitles { get; } = [
    "Accounting Manager",
    "Assistant Sales Agent",
    "Assistant Sales Representative",
    "Marketing Assistant",
    "Marketing Manager",
    "Order Administrator",
    "Owner",
    "Owner/Marketing Assistant",
    "Sales Agent",
    "Sales Associate",
    "Sales Manager",
    "Sales Representative",
    "Vice President, Sales"
];

public string ContactTypeNames()
    => Random.ArrayElement(contactTitles);
```

Now let's create a ContactType with a known title but with random first and last name.

```csharp
public ContactType ContactTypes()
{
    var data = new Faker<ContactType>()
        .RuleFor(p => p.ContactTypeIdentifier, p => p.Random.Int(1, 10))
        .RuleFor(p => p.ContactTitle, f => f.NorthWind().ContactTypeNames());

    return data.Generate();

}
```

## Summary

Although NorthWind database was the target, once the reader has studied and understands the code provided this will work for any data. The main example to focus on is Contact/ContactType.

## Source code

Clone the following [GitHub repository](https://github.com/karenpayneoregon/bogus-datasets)

### Requires

[Microsoft Visual Studio 2022](https://visualstudio.microsoft.com/vs/whatsnew/) with [NET8](https://dotnet.microsoft.com/en-us/download/visual-studio-sdks?cid=getdotnetsdk) Framework installed.