AJProds.EFDataSeeder.Core
7.0.0
dotnet add package AJProds.EFDataSeeder.Core --version 7.0.0
NuGet\Install-Package AJProds.EFDataSeeder.Core -Version 7.0.0
<PackageReference Include="AJProds.EFDataSeeder.Core" Version="7.0.0" />
paket add AJProds.EFDataSeeder.Core --version 7.0.0
#r "nuget: AJProds.EFDataSeeder.Core, 7.0.0"
// Install AJProds.EFDataSeeder.Core as a Cake Addin #addin nuget:?package=AJProds.EFDataSeeder.Core&version=7.0.0 // Install AJProds.EFDataSeeder.Core as a Cake Tool #tool nuget:?package=AJProds.EFDataSeeder.Core&version=7.0.0
Problem
There might be situations, when you need to seed some data with keeping the business logic in mind. Applying business logic and versioning of SQL migration scripts can be time-consuming. We should not forget about it would be great to be able to trace back the changes done in the database.
Examples
- You got a legacy project with a db schema you know you will need to modify during your upcoming implementations. You also know that, you will need to move some data from one table to another by applying business logic to it just before the app starts up for the first time with the latest migrations.
- You have a missing feature in your system, and you have a repetitive data manipulation (inject) task. For example, you need to modify user access controlled via db tables, because you do not have a UI, feature in the app to do so. You also would like to apply the business logic regarding the User Access of the project and you also would like to be able to trace back who modified user data and when?
Please note that you should not face with these problems. Instead of trying to patch problems like this, it worth to plan ahead and prepare for these kind of problems in the start. You should also check EF Core's data-seeding option: https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding
Solution
This package helps you seeding data by accessing the IoC container of the application.
You can seed the data with using the existing business logic already composed in your solution and access it later in the IoC of your app. All you need to do is simply to register ISeed implementations to your ServiceCollection.
Later on, you can see which seeds have been run via the sdr.SeederHistories
table.
How to use?
- Either generate the migrations for your DB, or reference the existing, db-specific nuget packages of this project.
- Register your
ISeed
implementations with theExtensions.RegisterDataSeeder<>
- Here goes your implementations of
ISeed
- Here goes your implementations of
- Register this project's tools and services via the
Extensions.RegisterDataSeederServices
- It is needed to use this project's tools
- Replace the
IHost.StartAsync
withExtensions.MigrateThenRunAsync
- It is needed to be able to run the
ISeed
withBeforeAppStart
option - It is needed to ensure the
SeederHistories
table got migrated
- It is needed to be able to run the
The example is from the AJProds.EFDataSeeder.Tests.Console
project
class Program
{
public const string CONNECTION_STRING =
@"Server=localhost\SQLEXPRESS;Initial Catalog=SeederTest;Trusted_Connection=True;MultipleActiveResultSets=true";
static async Task Main(string[] args)
{
await Host.CreateDefaultBuilder()
.ConfigureServices(ConfigureServices())
.Build()
.MigrateThenRunAsync(provider =>
// Ensure the TestDbContext's migration is run on start
provider.GetRequiredService<TestDbContext>()
.Database.MigrateAsync());
}
private static Action<IServiceCollection> ConfigureServices()
{
return collection =>
{
// Register seeders
collection.RegisterDataSeeder<AlwaysRunTestSeed>();
// My own, custom, test setup
collection.AddDbContext<TestDbContext>(builder => builder
.UseSqlServer(CONNECTION_STRING));
// EFSeeder setup - with an own EF Migration History table
collection.RegisterDataSeederServices(CONNECTION_STRING);
};
}
/// <summary>
/// My custom seed, that will run after all app start
/// </summary>
public class AlwaysRunTestSeed: ISeed
{
private readonly TestDbContext _dbContext;
public int Priority => 50;
public string SeedName => "Always Run seed";
public SeedMode Mode => SeedMode.AfterAppStart;
public bool AlwaysRun => true;
public AlwaysRunTestSeed(TestDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task SeedAsync()
{
_dbContext.Testees.Add(new Testee
{
Description = "Always Run seed"
});
await _dbContext.SaveChangesAsync();
}
}
}
Seed options
SeadMode.None
No ISeed
logic will be run. You need to find the BaseSeederManager
in your ioc
and run it with the SeedMode.None
argument.
var baseSeederManager = provider.GetRequiredService<BaseSeederManager>();
baseSeederManager.Seed(SeedMode.None);
SeadMode.BeforeAppStart
You must use the Extensions.MigrateThenRunAsync
with your HostBuilder
,
because this procedure will not start up the host until all migration
and seed (with SeedMode.BeforeAppStart
) has been run successfully.
await Host.CreateDefaultBuilder()
.ConfigureServices(ConfigureServices())
.Build()
.MigrateThenRunAsync();
SeadMode.AfterAppStart
After the host has started successfully, those ISeed
classes, that have been set to run AfterAppStart
will run in the background, in an IHostedService
.
ISeed.RunAlways ⇒ true
You can re-run the ISeed
procedures every time, when the application starts up.
Simply set the RunAlways
property to true in your ISeed
implementation.
TODO
- Bump versions to LTS → NET 6
- Add UI in a new project?
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Microsoft.EntityFrameworkCore (>= 7.0.3)
- Microsoft.EntityFrameworkCore.Relational (>= 7.0.3)
- Microsoft.Extensions.DependencyInjection (>= 7.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 7.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 7.0.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on AJProds.EFDataSeeder.Core:
Package | Downloads |
---|---|
AJProds.EFDataSeeder.PostgreSql
Seeding, manipulating data on app start with PostgreSQL |
|
AJProds.EFDataSeeder.MsSql
Seeding, manipulating data on app start with MSSQL |
GitHub repositories
This package is not used by any popular GitHub repositories.