Initial Baseline Data
TIP
As of Marten V5.0, this feature requires you to either use the integration with the .Net IHost
or use the new IDocumentStore.Advanced.ResetAllData()
method. See Initial Baseline Data for more information.
Marten supports seeding your database with initial data via the IInitialData
interface. For example:
public class InitialData: IInitialData
{
private readonly object[] _initialData;
public InitialData(params object[] initialData)
{
_initialData = initialData;
}
public async Task Populate(IDocumentStore store, CancellationToken cancellation)
{
await using var session = store.LightweightSession();
// Marten UPSERT will cater for existing records
session.Store(_initialData);
await session.SaveChangesAsync();
}
}
public static class InitialDatasets
{
public static readonly Company[] Companies =
{
new Company { Id = Guid.Parse("2219b6f7-7883-4629-95d5-1a8a6c74b244"), Name = "Netram Ltd." },
new Company { Id = Guid.Parse("642a3e95-5875-498e-8ca0-93639ddfebcd"), Name = "Acme Inc." }
};
public static readonly User[] Users =
{
new User { Id = Guid.Parse("331c15b4-b7bd-44d6-a804-b6879f99a65f"),FirstName = "Danger" , LastName = "Mouse" },
new User { Id = Guid.Parse("9d8ef25a-de9a-41e5-b72b-13f24b735883"), FirstName = "Speedy" , LastName = "Gonzales" }
};
}
Add your IInitialData
implementations as part of the configuration of your document store as follows:
using var host = await Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddMarten(opts =>
{
opts.DatabaseSchemaName = "Bug962";
opts.Connection(ConnectionSource.ConnectionString);
})
// Add as many implementations of IInitialData as you need
.InitializeWith(new InitialData(InitialDatasets.Companies), new InitialData(InitialDatasets.Users));
}).StartAsync();
var store = host.Services.GetRequiredService<IDocumentStore>();
IInitialData.Populate(IDocumentStore store)
will be executed for each configured entry as part of the initialization of your document store. They will be executed in the order they were added.
Applying Initial Data only in Testing
We think it's common that you'll use the IInitialData
mechanism strictly for test data setup. Let's say that you have a set of baseline data for testing that lives in your test project:
public class MyTestingData: IInitialData
{
public Task Populate(IDocumentStore store, CancellationToken cancellation)
{
// TODO -- add baseline test data here
return Task.CompletedTask;
}
}
Now, you'd like to use your exact application Marten configuration, but only for testing, add the MyTestingData
initial data set to the application's Marten configuration. You can do that as of Marten v5.1 with the IServiceCollection.InitializeMartenWith()
methods as shown in a sample below for a testing project:
// Use the configured host builder for your application
// by calling the Program.CreateHostBuilder() method from
// your application
// This would be slightly different using WebApplicationFactory,
// but the IServiceCollection mechanisms would be the same
var hostBuilder = Program.CreateHostBuilder(Array.Empty<string>());
// Add initial data to the application's Marten store
// in the test project
using var host = await hostBuilder
.ConfigureServices(services =>
{
services.InitializeMartenWith<MyTestingData>();
// or
services.InitializeMartenWith(new MyTestingData());
}).StartAsync();
// The MyTestingData initial data set would be applied at
// this point
var store = host.Services.GetRequiredService<IDocumentStore>();
// And in between tests, maybe do this to wipe out the store, then reapply
// MyTestingData:
await store.Advanced.ResetAllData();