Search code examples
c#asp.netentity-framework-corein-memory-database

ApplicationDbContext instance is creating again and again


I am working on a project with micro services.

  • Project 1: CustomerService (which provides API for editing customers)

  • Project 2: CoreService (which provides basic settings for .NET Core micro services. It contains ApplicationDbContext which is used in Project1. It also contains repositories for services, e.g. ICustomerRepository and its implementation CustomerRepostory).

Note: I am using an in-memory database.

My Program.cs for Project1 looks like this:

var builder = WebApplication.CreateBuilder(args);

var serviceProvider = builder.Services.AddDbContext<ApplicationDbContext>().BuildServiceProvider();

using (var context = serviceProvider.GetRequiredService<ApplicationDbContext>())
{
    context.SeedData();
}

builder.Services.AddHttpContextAccessor();
builder.Services.AddHttpClient();

builder.Services.AddScoped<IBaseService, BaseService>();

My Project2 Program.cs looks like this:

//add database related services
builder.Services.AddDbContext<ApplicationDbContext>(options =>
{
    options.UseInMemoryDatabase("InMemoryDB");
});

This is my ApplicationDbContext file in Project2:

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options) 
    {
    }

    public DbSet<Customer> Customers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseInMemoryDatabase("InMemoryDB");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<Customer>().HasKey(b => b.Id); // declaring Id as Primary key
    }

    public void SeedData()
    {
        // Ensure the database is created
        this.Database.EnsureCreated();

        if (!this.Customers.Any())
        {
            // Add initial data if the Bookings table is empty
            this.Customers.AddRange(
               new Customer
               {
                   Name = "Srijani",
                   Email = "abc@gmail.com",
                   Address = "Abcstraße 4, 123Hamburg",
                   ContactNumber = "9876541232"
               }
            );

            // Save changes after seeding data
            this.SaveChanges();
        }
    }
}

Now when I am running my project, and for example if I call any API from CustomerService, I do not see the seeded data from Project2 and my guess is it is just creating a new instance for ApplicationDbContext when I am calling the CustomerService API.

How can I prevent it and use the same instance of ApplicationDbContext?


Solution

  • It sounds like these are two separate processes. You cannot share an InMemory database instance between processes. The database seeded in Service 1 will be stored in Service 1's Process. Service 2 may reference Service 1 to be able to create an instance of the DbContext, but telling it to use an InMemory database even with the same name will just initialize an empty database in Service 2's process.

    If you want two (or more) web service projects where one is responsible for initializing and seeding a database that is shared with the other then you need to use an actual persisted, shared database such as SQL Server, SqlLite or PostgreSQL. The only way I know of that a second service could access the first service's in memory database would be to have it remote call into the first service for all data access. In this case the DbContext only exists in the first service and you're making web API calls over named pipes or such from services into Service 1 to access data.