static async Task Main(string[] args) { var tpyeResovler = new FullyQualifiedTypeNameTypeResolver("EventSourced.Example.Aggregate.Events.{0}, EventSourced.Example"); var connectionString = "Server=(local);Database=SqlStreamStoreDemo;Trusted_Connection=True;MultipleActiveResultSets=true"; var settings = new MsSqlStreamStoreSettings(connectionString); var streamStore = new MsSqlStreamStore(settings); streamStore.CreateSchema().GetAwaiter().GetResult(); var eventStore = new SqlStreamStoreEventStore(streamStore, tpyeResovler); var system = new EventSourcingSystem(eventStore); var counterCurrentValuesReadModel = new CounterCurrentValuesReadModel(system); var allPersistenceIdsReadModel = new AllPersistenceIdsReadModel(system); var counterId = Guid.Parse("8c936406-720a-45d4-b1e0-a95bd595943f"); var counter = await system.Get(() => new Counter(counterId)); if (!counter.IsInitialized()) { counter.Initialize(0); } counter.Increment(5); counter.Decrement(2); Thread.Sleep(5000); }
public static void EnsureSqlStreamStoreSchema <T>(MsSqlStreamStore streamStore, ILoggerFactory loggerFactory) { var logger = loggerFactory.CreateLogger <T>(); // TODO: Need to revisit this with a Consul lock Policy .Handle <SqlException>() .WaitAndRetry( 5, retryAttempt => { var value = Math.Pow(2, retryAttempt) / 4; var randomValue = new Random().Next((int)value * 3, (int)value * 5); logger.LogInformation("Retrying after {Seconds} seconds...", randomValue); return(TimeSpan.FromSeconds(randomValue)); }) .Execute(() => { logger.LogInformation("Ensuring the sql stream store schema."); var checkSchemaResult = streamStore.CheckSchema().GetAwaiter().GetResult(); if (!checkSchemaResult.IsMatch()) { streamStore.CreateSchema().GetAwaiter().GetResult(); } }); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, MsSqlStreamStore streamStore, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, HealthCheckService healthCheckService) { StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDatadog <Startup>( serviceProvider, loggerFactory, datadogToggle, debugDataDogToggle, _configuration["DataDog:ServiceName"]) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"exira.com - Dns API {groupName}", CustomExceptionHandlers = new IExceptionHandler[] { new DomainExceptionHandler(), new Exceptions.ApiExceptionHandler(), new AggregateNotFoundExceptionHandling(), new WrongExpectedVersionExceptionHandling(), new InvalidTopLevelDomainExceptionHandling(), new InvalidRecordTypeExceptionHandling(), new InvalidServiceTypeExceptionHandling(), new ValidationExceptionHandler(), } }, Server = { PoweredByName = "exira.com", ServerName = "exira.com" }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), }, }); }
public static async Task <IStreamStore> InitializeMsSqlStreamStore(string connectionString) { var streamStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings(connectionString)); await streamStore.CreateSchema(); return(streamStore); }
// private static BalanceProjection _balanceProjection; static async Task Main() { var streamId = new StreamId("Account:93aad7b7-f6d2-438f-911b-8eaba5695d48"); var store = new MsSqlStreamStore(new MsSqlStreamStoreSettings("Server=localhost;Database=eqx;User Id=sa;Password=p@ssw0rd;")); store.CreateSchema().Wait(); _streamStore = store; _account = new Account(_streamStore, streamId); // _balanceProjection = new BalanceProjection(_streamStore, streamId); var key = string.Empty; while (key != "X") { Console.WriteLine("D: Deposit"); Console.WriteLine("W: Withdrawal"); Console.WriteLine("B: Balance"); Console.WriteLine("T: Transactions"); Console.WriteLine("X: Exit"); Console.Write("> "); key = Console.ReadLine()?.ToUpperInvariant(); Console.WriteLine(); switch (key) { case "D": var depositAmount = GetAmount(); if (depositAmount.IsValid) { var depositTrx = await _account.Deposit(depositAmount.Amount); Console.WriteLine($"Deposited: {depositAmount.Amount:C} ({depositTrx})"); } break; case "W": var withdrawalAmount = GetAmount(); if (withdrawalAmount.IsValid) { var withdrawalTrx = await _account.Withdrawal(withdrawalAmount.Amount); Console.WriteLine($"Withdrawn: {withdrawalAmount.Amount:C} ({withdrawalTrx})"); } break; case "B": Balance(); break; case "T": await _account.Transactions(); break; } Console.WriteLine(); } }
public TraceStreamStore(MsSqlStreamStore streamStore, string serviceName, ISpanSource spanSource) { _streamStore = streamStore ?? throw new ArgumentException(nameof(streamStore)); _spanSource = spanSource ?? throw new ArgumentException(nameof(spanSource)); ServiceName = serviceName ?? DefaultServiceName; // TODO: Not sure about this _streamStore.OnDispose += OnDispose; }
public async Task <IStreamStore> GetStreamStore(string schema) { var settings = new MsSqlStreamStoreSettings(ConnectionString) { Schema = schema, }; var store = new MsSqlStreamStore(settings); await store.CreateSchema(); return(store); }
public async Task Save(Loan loan) { var streamId = GetStreamId(loan.Id); var events = loan.GetUncommittedEvents(); var expectedVersion = loan.Version - events.Length; var eventStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings("myconnectionString")); var messages = events.Select(Serialize).ToArray(); await eventStore.AppendToStream(streamId, expectedVersion, messages); loan.ClearUncommittedEvents(); }
public static async Task <IStreamStore> InitializeMsSqlStreamStoreWithSchemas(string connectionString, List <IEventSchema> eventSchemas) { var streamStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings(connectionString)); //foreach (var eventSchema in eventSchemas) //{ // await streamStore.CreateSchema(); //} return(streamStore); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, MsSqlStreamStore streamStore, HealthCheckService healthCheckService) { StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDatadog <Startup>( serviceProvider, loggerFactory, datadogToggle, debugDataDogToggle, _configuration["DataDog:ServiceName"]) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"exira.com - Account Projector API {groupName}", }, Server = { PoweredByName = "exira.com", ServerName = "exira.com" }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }); var projectionsManager = serviceProvider.GetRequiredService <IConnectedProjectionsManager>(); projectionsManager.Start(); }
static void Main(string[] args) { var cts = new CancellationTokenSource(); // We're first building configuraiton from the ini file // This contains the connection string var ini = new ConfigurationBuilder() .AddIniFile("Settings.ini") .Build(); // On a background thread, create the database and start initializing Task.Run(async() => await CreateDatabase(ini["ConnectionString"], cts.Token), cts.Token); IStreamStore streamStore = null; var sssConfig = new ConfigurationBuilder() // Add the stream store configuration data .AddStreamStore( subscribeToChanges: true, // When an error occurs while connecting to the database errorHandler: OnConnectError, streamStoreFactory: config => // Create sql stream store instance. Uses connection string from ini file. // Note, we're assigning an instance variable here, so we can dispose the instance later streamStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings(config["connectionString"])) ) // Also add the INI configuration data. This is where the connection string is read from .AddConfiguration(ini) .Build(); // Listen for configuration changes ChangeToken.OnChange(sssConfig.GetReloadToken, () => { Console.WriteLine("Settings changed:"); PrintSettings(sssConfig); }); // Print out the configuration settings present at startup Console.WriteLine("Found settings at startup:"); PrintSettings(sssConfig); // Keep going until enter is pressed. Console.ReadLine(); // Stop the background thread and dispose SSS cts.Cancel(); streamStore.Dispose(); }
private void SetupStreamStore(IServiceCollection services) { var streamStore = new MsSqlStreamStore(_msSqlStreamStoreSettings); services.AddSingleton <IStreamStore>(x => streamStore); var schema = streamStore.CheckSchema().GetAwaiter().GetResult(); if (!schema.IsMatch()) { streamStore.CreateSchema(); } }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, MsSqlStreamStore streamStore, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, HealthCheckService healthCheckService) { StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDatadog <Startup>( serviceProvider, loggerFactory, datadogToggle, debugDataDogToggle, _configuration["DataDog:ServiceName"]) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"Basisregisters Vlaanderen - Dienstverleningsregister API {groupName}", CustomExceptionHandlers = new [] { new GetOrganisationFailedHandler() } }, MiddlewareHooks = { AfterApiExceptionHandler = x => x.UseAuthentication(), AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }); }
public async Task <MsSqlStreamStore> GetMsSqlStreamStore() { await CreateDatabase(); var settings = new MsSqlStreamStoreSettings(ConnectionString) { Schema = _schema, GetUtcNow = () => GetUtcNow() }; var store = new MsSqlStreamStore(settings); await store.CreateSchema(); return(store); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, MsSqlStreamStore streamStore) { StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); if (datadogToggle.FeatureEnabled) { if (debugDataDogToggle.FeatureEnabled) { StartupHelpers.SetupSourceListener(serviceProvider.GetRequiredService <TraceSource>()); } app.UseDataDogTracing( serviceProvider.GetRequiredService <TraceSource>(), _configuration["DataDog:ServiceName"], pathToCheck => pathToCheck != "/"); } app.UseDefaultForApi(new StartupOptions { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"Basisregisters Vlaanderen - Bank Account Number Registry API {groupName}", CustomExceptionHandlers = new IExceptionHandler[] { new ValidationExceptionHandling(), } }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), }, }); }
protected override void Load(ContainerBuilder builder) { builder.RegisterType <SqlConnectionFactory>() .As <ISqlConnectionFactory>() .WithParameter("connectionString", _databaseConnectionString) .InstancePerLifetimeScope(); IStreamStore streamStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings(_databaseConnectionString) { Schema = DatabaseSchema.Name }); builder.RegisterInstance(streamStore); builder.RegisterType <SqlStreamAggregateStore>() .As <IAggregateStore>() .InstancePerLifetimeScope(); builder.RegisterType <SqlServerCheckpointStore>() .As <ICheckpointStore>() .InstancePerLifetimeScope(); var applicationAssembly = typeof(IProjector).Assembly; builder.RegisterAssemblyTypes(applicationAssembly) .Where(type => type.Name.EndsWith("Projector")) .AsImplementedInterfaces() .InstancePerLifetimeScope() .FindConstructorsWith(new AllConstructorFinder()); builder.RegisterType <SubscriptionsManager>() .As <SubscriptionsManager>() .SingleInstance(); var infrastructureAssembly = ThisAssembly; builder.RegisterAssemblyTypes(infrastructureAssembly) .Where(type => type.Name.EndsWith("Repository")) .AsImplementedInterfaces() .InstancePerLifetimeScope() .FindConstructorsWith(new AllConstructorFinder());; }
private MsSqlStreamStore GetStore() { var configurationBuilder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); var environment = Environment.GetEnvironmentVariable("NETCORE_ENVIRONMENT"); var isDevelopment = string.Equals(environment, "development", StringComparison.OrdinalIgnoreCase); if (isDevelopment) { configurationBuilder.AddUserSecrets(Assembly.GetCallingAssembly()); } var configuration = configurationBuilder.Build(); var connectionString = configuration["EventStore:SqlStreamStore:ConnectionString"]; var settings = new MsSqlStreamStoreSettings(connectionString); var store = new MsSqlStreamStore(settings); return(store); }
public async Task <Loan> Get(Guid id) { var loan = new Loan(id); var streamId = GetStreamId(id); var eventStore = new MsSqlStreamStore(new MsSqlStreamStoreSettings("myconnectionString")); var position = 0; ReadStreamPage page; do { page = await eventStore.ReadStreamForwards(streamId, position, ReadPageSize); foreach (var message in page.Messages) { var evt = await Deserialize(message); loan.ApplyEvent(evt); } position = page.NextStreamVersion; } while (!page.IsEnd); return(loan); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, MsSqlStreamStore streamStore, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, HealthCheckService healthCheckService) { StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDataDog <Startup>(new DataDogOptions { Common = { ServiceProvider = serviceProvider, LoggerFactory = loggerFactory }, Toggles = { Enable = datadogToggle, Debug = debugDataDogToggle }, Tracing = { ServiceName = _configuration["DataDog:ServiceName"], } }) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"Basisregisters Vlaanderen - Municipality Registry API {groupName}", CSharpClientOptions = { ClassName = "MunicipalityRegistryCrabImport", Namespace = "Be.Vlaanderen.Basisregisters" }, TypeScriptClientOptions = { ClassName = "MunicipalityRegistryCrabImport" } }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }) .UseIdempotencyDatabaseMigrations() .UseCrabImportMigrations(); StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); }
public async Task Ping(CancellationToken cancellationToken = default) { var eventStore = new MsSqlStreamStore(settings); await eventStore.CheckSchema(cancellationToken); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, MsSqlStreamStore streamStore, HealthCheckService healthCheckService) { StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDataDog <Startup>(new DataDogOptions { Common = { ServiceProvider = serviceProvider, LoggerFactory = loggerFactory }, Toggles = { Enable = datadogToggle, Debug = debugDataDogToggle }, Tracing = { ServiceName = _configuration["DataDog:ServiceName"], } }) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"Example Registry Projector API {groupName}", CSharpClientOptions = { ClassName = "ExampleRegistry", Namespace = "ExampleRegistry.Projector" }, TypeScriptClientOptions = { ClassName = "ExampleRegistry" }, }, Server = { PoweredByName = "Vlaamse overheid - Basisregisters Vlaanderen", ServerName = "agentschap Informatie Vlaanderen" }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }) .UseProjectionsManager(new ProjectionsManagerOptions { Common = { ServiceProvider = serviceProvider, ApplicationLifetime = appLifetime } }); }
public SqlStreamStoreConsumer(string name, string connectionString) { _name = name; _connectionString = connectionString; _store = new MsSqlStreamStore(new MsSqlStreamStoreSettings(connectionString)); }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, MsSqlStreamStore streamStore, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, HealthCheckService healthCheckService) { StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDataDog <Startup>(new DataDogOptions { Common = { ServiceProvider = serviceProvider, LoggerFactory = loggerFactory }, Toggles = { Enable = datadogToggle, Debug = debugDataDogToggle }, Tracing = { ServiceName = _configuration["DataDog:ServiceName"], } }) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"exira.com - Dns Projector API {groupName}", CustomExceptionHandlers = new IExceptionHandler[] { new ValidationExceptionHandler(), } }, Server = { PoweredByName = "exira.com", ServerName = "exira.com" }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }) .UseProjectionsManager(new ProjectionsManagerOptions { Common = { ServiceProvider = serviceProvider, ApplicationLifetime = appLifetime } }); }
public TraceStreamStore(MsSqlStreamStore streamStore, string serviceName) : this(streamStore, serviceName, TraceContextSpanSource.Instance) { }
public TraceStreamStore(MsSqlStreamStore streamStore) : this(streamStore, DefaultServiceName, TraceContextSpanSource.Instance) { }
public void Configure( IServiceProvider serviceProvider, IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime appLifetime, ILoggerFactory loggerFactory, IApiVersionDescriptionProvider apiVersionProvider, MsSqlStreamStore streamStore, ApiDataDogToggle datadogToggle, ApiDebugDataDogToggle debugDataDogToggle, HealthCheckService healthCheckService) { StartupHelpers.EnsureSqlStreamStoreSchema <Startup>(streamStore, loggerFactory); app .UseDataDog <Startup>(new DataDogOptions { Common = { ServiceProvider = serviceProvider, LoggerFactory = loggerFactory }, Toggles = { Enable = datadogToggle, Debug = debugDataDogToggle }, Tracing = { ServiceName = _configuration["DataDog:ServiceName"], } }) .UseDefaultForApi(new StartupUseOptions { Common = { ApplicationContainer = _applicationContainer, ServiceProvider = serviceProvider, HostingEnvironment = env, ApplicationLifetime = appLifetime, LoggerFactory = loggerFactory, }, Api = { VersionProvider = apiVersionProvider, Info = groupName => $"Basisregisters Vlaanderen - Address Registry API {groupName}", CSharpClientOptions = { ClassName = "AddressRegistryCrabImport", Namespace = "Be.Vlaanderen.Basisregisters" }, TypeScriptClientOptions = { ClassName = "AddressRegistryCrabImport" } }, Server = { PoweredByName = "Vlaamse overheid - Basisregisters Vlaanderen", ServerName = "agentschap Informatie Vlaanderen" }, MiddlewareHooks = { AfterMiddleware = x => x.UseMiddleware <AddNoCacheHeadersMiddleware>(), } }); app.UseIdempotencyDatabaseMigrations() .UseCrabImportMigrations(); MigrationsHelper.Run( _configuration.GetConnectionString("Sequences"), serviceProvider.GetService <ILoggerFactory>()); new LegacyContextMigrationFactory() .CreateMigrator(_configuration, _loggerFactory) .MigrateAsync(new CancellationToken()) .GetAwaiter() .GetResult(); StartupHelpers.CheckDatabases(healthCheckService, DatabaseTag).GetAwaiter().GetResult(); }
private static async Task CreateDatabase(string connectionString, CancellationToken ct) { // There is a while true loop here, because sometimes after creating the db, the db is not available always. // There are much better ways of handling this, but I couldn't be bothered right now;) while (true) { try { await Task.Delay(1000); Console.WriteLine("Creating database schema"); await Task.Delay(3000); var mgr = new DatabaseManager(connectionString); mgr.EnsureDatabaseExists(10, 10); await Task.Delay(2000, ct); var msSqlStreamStoreSettings = new MsSqlStreamStoreSettings(connectionString); var store = new MsSqlStreamStore(msSqlStreamStoreSettings); if (!(await store.CheckSchema(ct)).IsMatch()) { await store.CreateSchema(ct); } var repo = new StreamStoreConfigRepository(store); Console.WriteLine("Now generating 20 changes:"); for (int i = 0; i < 20; i++) { await Task.Delay(1000, ct); await repo.Modify(ct, ("setting1", "new value, written at: " + DateTime.Now.ToLongTimeString())); } // Delay for a while, so the latest version can be printed. await Task.Delay(1000, ct); var history = await repo.GetSettingsHistory(ct); Console.WriteLine($"There have historically been:{history.Count} versions: "); foreach (var setting in history) { Console.WriteLine($"\t- Version: {setting.Version}, setting1 = '{setting["setting1"]}', ModifiedKeys: [{string.Join(',', setting.ModifiedKeys)}]"); } Console.WriteLine($"Now reverting back to the first version's data: {history.First().Version}"); // Now revert back to the first version (this actually creates a new version, with the old data in it) await repo.RevertToVersion(history.First(), ct); // Completed succesfully. End the function return; } catch (Exception ex) { Console.WriteLine("error while creating database: " + ex.Message + " (will retry)"); } } }