You've already forked Extensions.Configuration.EntityFrameworkCore
Working implementation
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Options = RAIC.Extensions.Configuration.EntityFrameworkCore.PostgreSQL.PostgreSQLNotificationConfigurationReloaderOptions;
|
||||
|
||||
namespace RAIC.Extensions.Configuration.EntityFrameworkCore.PostgreSQL.Extensions;
|
||||
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
|
||||
public delegate OptionsBuilder<T> OptionsTransformer<T>(OptionsBuilder<T> transform) where T : class;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="PostgreSQLNotificationConfigurationReloader"/> (a <see cref="Microsoft.Extensions.Hosting.IHostedService"/> implementation)
|
||||
/// and supporting services to the <see cref="IServiceCollection"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDbContext">Type of the <see cref="DbContext"/> to use to obtain the underlying database connection</typeparam>
|
||||
/// <param name="services">The service collection to add the services too</param>
|
||||
/// <returns>The service collection it was called on now with added services</returns>
|
||||
public static IServiceCollection AddPostgreSQLNotificationConfigurationReloadService<TDbContext>(this IServiceCollection services)
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
return services.AddPostgreSQLNotificationConfigurationReloadService<TDbContext>(static _ => { });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="PostgreSQLNotificationConfigurationReloader"/> (a <see cref="Microsoft.Extensions.Hosting.IHostedService"/> implementation)
|
||||
/// and supporting services to the <see cref="IServiceCollection"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDbContext">Type of the <see cref="DbContext"/> to use to obtain the underlying database connection</typeparam>
|
||||
/// <param name="services">The service collection to add the services too</param>
|
||||
/// <param name="configure">
|
||||
/// Action to manually configure the <see cref="Options"/> instance consumed by <see cref="PostgreSQLNotificationConfigurationReloader"/> eg.
|
||||
/// <code>
|
||||
/// options => {
|
||||
/// options.DebounceInterval = TimeSpan.FromSeconds(2);
|
||||
/// options.ChannelName = "awesome_channel";
|
||||
/// }
|
||||
/// </code>
|
||||
/// </param>
|
||||
/// <returns>The service collection it was called on now with added services</returns>
|
||||
public static IServiceCollection AddPostgreSQLNotificationConfigurationReloadService<TDbContext>(this IServiceCollection services, Action<Options> configure)
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
var optionsBuilder = services.AddCoreServices<TDbContext>();
|
||||
|
||||
optionsBuilder.Configure(configure);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds <see cref="PostgreSQLNotificationConfigurationReloader"/> (a <see cref="Microsoft.Extensions.Hosting.IHostedService"/> implementation)
|
||||
/// and supporting services to the <see cref="IServiceCollection"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDbContext">Type of the <see cref="DbContext"/> to use to obtain the underlying database connection</typeparam>
|
||||
/// <param name="services">The service collection to add the services too</param>
|
||||
/// <param name="optionsTransform">
|
||||
/// Transformer delegate to apply to the <see cref="Options"/> instance consumed by <see cref="PostgreSQLNotificationConfigurationReloader"/> eg.
|
||||
/// <code>
|
||||
/// optionsBuilder => optionsBuilder.Bind(context.Configuration)
|
||||
/// </code>
|
||||
/// </param>
|
||||
/// <returns>The service collection it was called on now with added services</returns>
|
||||
public static IServiceCollection AddPostgreSQLNotificationConfigurationReloadService<TDbContext>(this IServiceCollection services, OptionsTransformer<Options> optionsTransform)
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
var optionsBuilder = services.AddCoreServices<TDbContext>();
|
||||
|
||||
optionsTransform(optionsBuilder);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
|
||||
private static OptionsBuilder<Options> AddCoreServices<TDbContext>(this IServiceCollection services)
|
||||
where TDbContext : DbContext
|
||||
{
|
||||
services.AddSingleton(static provider => provider.GetRequiredService<TDbContext>().Database)
|
||||
.AddSingleton(static provider =>
|
||||
{
|
||||
var configRoot = (IConfigurationRoot)provider.GetRequiredService<IConfiguration>(); // DEBT: Is this cast always safe?
|
||||
return configRoot.Providers.OfType<IEntityFrameworkCoreDbSetConfigurationProvider>().Single();
|
||||
})
|
||||
.AddHostedService<PostgreSQLNotificationConfigurationReloader>();
|
||||
|
||||
return services.AddOptions<Options>().ValidateDataAnnotations().ValidateOnStart();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
CREATE OR REPLACE FUNCTION settings_poc.notify_setting_change()
|
||||
RETURNS trigger AS $$
|
||||
BEGIN
|
||||
PERFORM pg_notify('setting_channel', concat(NEW.key,'=',NEW.value));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION settings_poc.notify_setting_remove()
|
||||
RETURNS trigger AS $$
|
||||
BEGIN
|
||||
PERFORM pg_notify('setting_channel', OLD.key);
|
||||
RETURN OLD;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER setting_insert_trigger
|
||||
AFTER INSERT ON settings_poc.settings
|
||||
FOR EACH ROW EXECUTE FUNCTION settings_poc.notify_setting_change();
|
||||
|
||||
CREATE TRIGGER setting_update_trigger
|
||||
AFTER UPDATE ON settings_poc.settings
|
||||
FOR EACH ROW WHEN (NEW.value <> OLD.value) EXECUTE FUNCTION settings_poc.notify_setting_change();
|
||||
|
||||
CREATE TRIGGER setting_delete_trigger
|
||||
AFTER DELETE ON settings_poc.settings
|
||||
FOR EACH ROW EXECUTE FUNCTION settings_poc.notify_setting_remove();
|
||||
|
||||
*
|
||||
*/
|
||||
Reference in New Issue
Block a user