ASP.NET Core 2.2 - In Memory Entities

This article will demonstrate the creation of a small in-memory database which I will use in upcoming articles about table functions. I will assume you have created a new ASP.NET Core 2.2 Razor Pages project. I won't use Identity or Individual User Accounts.

The FREE ASP.NET Core 6.0 - Demos And Utilities Project includes a Table Functions Demo. Access to the source code is free for registered users at Manage > Assets.

To describe table functions, I wanted a simple set of entities with a few different property types. I started my research with the article Using EF Core's InMemory Provider To Store A "Database" In Memory by Matthew Jones. I wanted more records with fields which could be filtered and sorted. I used lists of fruit, vegetable and spice names from Fruits and Vegetables: List, Names & Pictures to help create the entities. Using an in-memory database allowed quick data modification for testing purposes.

Let's start with the entity class. I will use an enum for FoodType. Create a new root folder named Entities.

Add a new class named Food to the Entities folder:
public enum FoodType
{
    All,
    Fruit,
    Vegtable,
    Other
}

public class Food
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public FoodType FoodType { get; set; }
    public bool ColdStore { get; set; }
    public DateTime Date { get; set; }
}

We need a DbContext for injection. Create a new root folder named Data.

Add a new class named FoodDbContext to the Data folder:
public class FoodDbContext : DbContext
{
    public FoodDbContext(DbContextOptions options)
        : base(options)
    {
    }

    public DbSet<Food> Foods { get; set; }
}

Employ the UseInMemoryDatabase option when adding the DbContext to services.

Edit Startup.cs > ConfigureServices, add the DbContext:
services.AddDbContext<FoodDbContext>(options => options.UseInMemoryDatabase(databaseName: "Foods"));

I like Matthew Jones' DataGenerator approach which creates the database at application start. Create a new root folder named Services.

Add a new class named DataGenerator to the Services folder:
public class DataGenerator
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new FoodDbContext(
            serviceProvider.GetRequiredService<DbContextOptions<FoodDbContext>>()))
        {
            // Look for any foods.
            if (context.Foods.Any())
            {
                return;   // Data was already seeded
            }

            int i = 0, id = 0, coldStoreFactor = 3;
            DateTime baseTime = DateTime.Now;

            var fruits = @"Apple,Watermelon,Orange,Pear,Cherry,Strawberry,Nectarine,
Grape,Mango,Blueberry,Pomegranate,Starfruit,Plum,Banana,Raspberry,Mandarin,Jackfruit,
Papaya,Kiwi,Pineapple,Lime,Lemon,Apricot,Grapefruit,Melon,Coconut,Avocado,Peach";
            var fruitList = fruits.Split(',').ToList();
            foreach (string fruit in fruitList)
            {
                i++;
                id++;
                context.Foods.Add(new Food()
                {
                    Id = id,
                    Name = fruit.Trim(),
                    FoodType = FoodType.Fruit,
                    ColdStore = i % coldStoreFactor == 0,
                    Date = baseTime.AddHours(i).AddMinutes(id)
                });
                context.SaveChanges();
            };

            i = 0;
            var vegtables = @"Corn,Mushroom,Broccoli,Cucumber,Red bell pepper,
Tomato,Rutabaga,Carrot,Brussels sprout,Pumpkin,Cabbage,Potato,Eggplant,
Sweet potato,Turnip,Zucchini,Green chilli,Onion,Lettuce,Radish,Pea,Asparagus,Celery,
Green pepper,French beans,Spinach,Beet,Red chili peppers,Bean";
            var vegtableList = vegtables.Split(',').ToList();
            foreach (string vegtable in vegtableList)
            {
                i++;
                id++;
                context.Foods.Add(new Food()
                {
                    Id = id,
                    Name = vegtable.Trim(),
                    FoodType = FoodType.Vegtable,
                    ColdStore = i % coldStoreFactor == 0,
                    Date = baseTime.AddHours(i).AddMinutes(id)
                });
                context.SaveChanges();
            };

            i = 0;
            var spices = @"Cilantro,Artichoke,Rosemary,Bay leaves,Mint leaves,Basil,Clove,
Olive,Shallot,Turmeric,Garlic,Ginger,Onion,Green onions,Lemongrass,Chives,Green chili";
            var spiceList = spices.Split(',').ToList();
            foreach (string spice in spiceList)
            {
                i++;
                id++;
                context.Foods.Add(new Food()
                {
                    Id = id,
                    Name = spice.Trim(),
                    FoodType = FoodType.Other,
                    ColdStore = i % coldStoreFactor == 0,
                    Date = baseTime.AddHours(i).AddMinutes(id)
                });
                context.SaveChanges();
            };
        }
    }
}

Call the DataGenerator > Initialize method after the build and before the run commands for CreateWebHostBuilder.

Edit Program.cs > Main:
//CreateWebHostBuilder(args).Build().Run();

//1. Get the IWebHost which will host this application.
var host = CreateWebHostBuilder(args).Build();

//2. Find the service layer within our scope.
using (var scope = host.Services.CreateScope())
{
    //3. Get the instance of FoodDbContext in our services layer
    var services = scope.ServiceProvider;
    var context = services.GetRequiredService<FoodDbContext>();

    //4. Call the DataGenerator to create sample data
    DataGenerator.Initialize(services);
}

//Continue to run the application
host.Run();

Resolve any namespace issues.

Access the Food entities from any page using dependency injection.

Edit Index.cs > IndexModel:
private readonly FoodDbContext _context;

public DataModel(FoodDbContext context)
{
    _context = context;
}

public IList<Food> Foods { get; set; } = new List<Food>();

public void OnGet()
{
    Foods = _context.Foods.ToList();
}
Edit Index.cshtml, add the table:
<div class="row">
    <div class="col-12">
        <table class="table">
            <thead>
                <tr>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Id)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Name)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].FoodType)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].ColdStore)
                    </th>
                    <th>
                        @Html.DisplayNameFor(model => model.Foods[0].Date)
                    </th>
                </tr>
            </thead>
            <tbody>
                @if (Model.Foods.Count > 0)
                {
                    foreach (var item in Model.Foods)
                    {
                        <tr>
                            <td>
                                @Html.DisplayFor(modelItem => item.Id)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Name)
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.FoodType)
                            </td>
                            <td>
                                <input type="checkbox" asp-for="@item.ColdStore">
                            </td>
                            <td>
                                @Html.DisplayFor(modelItem => item.Date)
                            </td>
                        </tr>
                    }
                }
                else
                {
                    <tr>
                        <td colspan="5" class="text-center">
                            No Food Found
                        </td>
                    </tr>
                }

            </tbody>
        </table>
    </div>
</div>

Build, run and test.

In Memory Data.
Update 12/30/2021

Announced the ASP.NET Core 6.0 - Demos And Utilities Project. Updated articles, asset and topic links.

Ken Haggerty
Created 08/15/19
Updated 08/28/22 02:14 GMT

Log In or Reset Quota to read more.

Article Tags:

EF Core Model
Successfully completed. Thank you for contributing.
Processing...
Something went wrong. Please try again.
Contribute to enjoy content without advertisments.
You can contribute without registering.

Comments(0)

Loading...
Loading...

Not accepting new comments.

Submit your comment. Comments are moderated.

User Image.
DisplayedName - Member Since ?