using Elsa.Common.Entities;
using Elsa.Extensions;
using Elsa.Features.Abstractions;
using Elsa.Features.Attributes;
using Elsa.Features.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.DependencyInjection;
namespace Elsa.EntityFrameworkCore;
///
/// Base class for features that require Entity Framework Core.
///
/// The type of the database context.
/// The type of the feature.
[DependsOn(typeof(CommonPersistenceFeature))]
public abstract class PersistenceFeatureBase(IModule module) : FeatureBase(module)
where TDbContext : ElsaDbContextBase
{
///
/// Gets or sets a value indicating whether to use context pooling.
///
public virtual bool UseContextPooling { get; set; }
///
/// Gets or sets a value indicating whether to run migrations.
///
public virtual bool RunMigrations { get; set; } = true;
///
/// Gets or sets the lifetime of the . Defaults to .
///
public ServiceLifetime DbContextFactoryLifetime { get; set; } = ServiceLifetime.Scoped;
///
/// Gets or sets the callback used to configure the .
///
public virtual Action DbContextOptionsBuilder { get; set; } = null!;
public override void ConfigureHostedServices()
{
if (RunMigrations)
ConfigureMigrations();
}
///
public override void Apply()
{
if (DbContextOptionsBuilder == null)
throw new InvalidOperationException("The DbContextOptionsBuilder must be configured.");
Action setup = (sp, opts) =>
{
opts.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning));
DbContextOptionsBuilder(sp, opts);
};
if (UseContextPooling)
Services.AddPooledDbContextFactory(setup);
else
Services.AddDbContextFactory(setup, DbContextFactoryLifetime);
Services.Decorate, TenantAwareDbContextFactory>();
}
protected virtual void ConfigureMigrations()
{
Services.AddStartupTask>();
}
///
/// Adds a store to the service collection.
///
/// The type of the entity.
/// The type of the store.
protected void AddStore() where TEntity : class, new() where TStore : class
{
Services
.AddScoped>()
.AddScoped()
;
}
///
/// Adds an entity store to the service collection.
///
/// The type of the entity.
/// The type of the store.
protected void AddEntityStore() where TEntity : Entity, new() where TStore : class
{
Services
.AddScoped>()
.AddScoped()
;
}
}