public void TestAddBookAddedActionToUpdateDates() { //SETUP var options = SqliteInMemory.CreateOptions <ExampleDbContext>(); var config = new GenericEventRunnerConfig(); config.AddActionToRunAfterDetectChanges <ExampleDbContext>(localContext => { foreach (var entity in localContext.ChangeTracker.Entries() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)) { var tracked = entity.Entity as ICreatedUpdated; tracked?.LogChange(entity.State == EntityState.Added, entity); } }); var context = options.CreateAndSeedDbWithDiForHandlers <OrderCreatedHandler>(null, config); { //ATTEMPT var book = Book.CreateBookWithEvent("test"); context.Add(book); context.SaveChanges(); book.WhenCreatedUtc.Subtract(DateTime.UtcNow).TotalMilliseconds.ShouldBeInRange(-100, 10); Thread.Sleep(1000); book.ChangeTitle("new title"); context.SaveChanges(); //VERIFY book.LastUpdatedUtc.Subtract(DateTime.UtcNow).TotalMilliseconds.ShouldBeInRange(-100, 10); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) //#A { services.AddControllersWithViews() //#B //.AddRazorRuntimeCompilation() //This recompile a razor page if you edit it while the app is running //Added this because my logs display needs the enum as a string .AddJsonOptions(opts => { opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); var bookAppSettings = Configuration.GetBookAppSettings(); services.AddSingleton(bookAppSettings); //This gets the correct sql connection string based on the BookAppSettings var sqlConnection = Configuration.GetCorrectSqlConnection(bookAppSettings); //This registers both DbContext. Each MUST have a unique MigrationsHistoryTable for Migrations to work services.AddDbContext <BookDbContext>( options => options.UseSqlServer(sqlConnection, dbOptions => dbOptions.MigrationsHistoryTable("BookMigrationHistoryName"))); services.AddDbContext <OrderDbContext>( options => options.UseSqlServer(sqlConnection, dbOptions => dbOptions.MigrationsHistoryTable("OrderMigrationHistoryName"))); services.AddHttpContextAccessor(); services.Configure <BookAppSettings>(options => Configuration.GetSection(nameof(BookAppSettings)).Bind(options)); services.AddSingleton <IMenuBuilder, MenuBuilder>(); //This registers all the services across all the projects in this application var diLogs = services.RegisterAssemblyPublicNonGenericClasses( Assembly.GetAssembly(typeof(IDisplayOrdersService)), Assembly.GetAssembly(typeof(IPlaceOrderBizLogic)), Assembly.GetAssembly(typeof(IPlaceOrderDbAccess))) .AsPublicImplementedInterfaces(); //BookApp.Books startup var test = services.RegisterBooksServices(Configuration); //Register EfCore.GenericEventRunner var eventConfig = new GenericEventRunnerConfig(); eventConfig.RegisterSaveChangesExceptionHandler <BookDbContext>(BookWithEventsConcurrencyHandler.HandleCacheValuesConcurrency); eventConfig.AddActionToRunAfterDetectChanges <BookDbContext>(BookDetectChangesExtensions.ChangeChecker); var logs = services.RegisterGenericEventRunner(eventConfig, Assembly.GetAssembly(typeof(ReviewAddedHandler)) //SQL cached values event handlers ); //Register EfCoreGenericServices services.ConfigureGenericServicesEntities(typeof(BookDbContext)) .ScanAssemblesForDtos( BooksStartupInfo.GenericServiceAssemblies.ToArray() ).RegisterGenericServices(); var softLogs = services.RegisterSoftDelServicesAndYourConfigurations(); }
public void TestGenericEventRunnerConfigAddActionToRunAfterDetectChangeOk() { //SETUP var options = SqliteInMemory.CreateOptions <BookDbContext>(); var eventConfig = new GenericEventRunnerConfig(); eventConfig.AddActionToRunAfterDetectChanges <BookDbContext>(localContext => localContext.ChangeChecker()); using var context = options.CreateDbWithDiForHandlers <BookDbContext, ReviewAddedHandler>(null, eventConfig); context.Database.EnsureCreated(); //ATTEMPT var books = context.SeedDatabaseFourBooks(); //VERIFY var timeNow = DateTime.UtcNow; books.ForEach(x => x.LastUpdatedUtc.ShouldBeInRange(DateTime.UtcNow.AddMilliseconds(-500), timeNow)); books.ForEach(x => x.NotUpdatedYet.ShouldBeTrue()); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) //#A { services.AddControllersWithViews() //#B //.AddRazorRuntimeCompilation() //This recompile a razor page if you edit it while the app is running //Added this because my logs display needs the enum as a string .AddJsonOptions(opts => { opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); var connectionString = Configuration.GetConnectionString("DefaultConnection"); //This registers both DbContext. Each MUST have a unique MigrationsHistoryTable for Migrations to work services.AddDbContext <BookDbContext>( options => options.UseSqlServer(connectionString, dbOptions => dbOptions.MigrationsHistoryTable("BookMigrationHistoryName"))); services.AddHttpContextAccessor(); //ModMod.Books startup var test = services.RegisterBooksServices(Configuration); //Register EfCore.GenericEventRunner var eventConfig = new GenericEventRunnerConfig(); eventConfig.RegisterSaveChangesExceptionHandler <BookDbContext>(BookWithEventsConcurrencyHandler.HandleCacheValuesConcurrency); eventConfig.AddActionToRunAfterDetectChanges <BookDbContext>(BookDetectChangesExtensions.ChangeChecker); var logs = services.RegisterGenericEventRunner(eventConfig, Assembly.GetAssembly(typeof(ReviewAddedHandler)) //SQL cached values event handlers ); //Register EfCoreGenericServices services.ConfigureGenericServicesEntities(typeof(BookDbContext)) .ScanAssemblesForDtos( BooksStartupInfo.GenericServiceAssemblies.ToArray() ).RegisterGenericServices(); var softLogs = services.RegisterSoftDelServicesAndYourConfigurations(); }
public async Task TestWriteBooksAsyncCheckAddUpdateDates() { //SETUP var fileDir = Path.Combine(TestData.GetTestDataDir()); var options = SqliteInMemory.CreateOptions <BookDbContext>(); options.TurnOffDispose(); var timeNow = DateTime.UtcNow; var eventConfig = new GenericEventRunnerConfig { NotUsingDuringSaveHandlers = true }; eventConfig.AddActionToRunAfterDetectChanges <BookDbContext>(localContext => localContext.ChangeChecker()); using var context = options.CreateDbWithDiForHandlers <BookDbContext, ReviewAddedHandler>(null, eventConfig); context.Database.EnsureCreated(); await context.SeedDatabaseWithBooksAsync(fileDir); //The LastUpdatedUtc is set via events context.ChangeTracker.Clear(); //ATTEMPT var serviceProvider = BuildServiceProvider(options); var generator = new BookGenerator(serviceProvider); await generator.WriteBooksAsync(fileDir, false, 20, true, default); //VERIFY var books = context.Books .Include(x => x.Reviews) .Include(x => x.AuthorsLink).ToList(); books.All(x => x.LastUpdatedUtc >= timeNow).ShouldBeTrue(); books.SelectMany(x => x.Reviews).All(x => x.LastUpdatedUtc >= timeNow).ShouldBeTrue(); books.SelectMany(x => x.AuthorsLink).All(x => x.LastUpdatedUtc >= timeNow).ShouldBeTrue(); options.ManualDispose(); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) //#A { services.AddControllersWithViews() //#B .AddRazorRuntimeCompilation() //This recompile a razor page if you edit it while the app is running //Added this because my logs display needs the enum as a string .AddJsonOptions(opts => { opts.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); var bookAppSettings = Configuration.GetBookAppSettings(); services.AddSingleton(bookAppSettings); //This gets the correct sql connection string based on the BookAppSettings var sqlConnection = Configuration.GetCorrectSqlConnection(bookAppSettings); //This registers both DbContext. Each MUST have a unique MigrationsHistoryTable for Migrations to work services.AddDbContext <BookDbContext>( options => options.UseSqlServer(sqlConnection, dbOptions => dbOptions.MigrationsHistoryTable("BookMigrationHistoryName"))); services.AddDbContext <OrderDbContext>( options => options.UseSqlServer(sqlConnection, dbOptions => dbOptions.MigrationsHistoryTable("OrderMigrationHistoryName"))); var cosmosSettings = Configuration.GetCosmosDbSettings(bookAppSettings); if (cosmosSettings != null) { services.AddDbContext <CosmosDbContext>(options => options.UseCosmos( cosmosSettings.ConnectionString, cosmosSettings.DatabaseName)); } else { services.AddSingleton <CosmosDbContext>(_ => null); } services.AddHttpContextAccessor(); services.Configure <BookAppSettings>(options => Configuration.GetSection(nameof(BookAppSettings)).Bind(options)); services.AddSingleton <IMenuBuilder, MenuBuilder>(); //This registers all the services across all the projects in this application var diLogs = services.RegisterAssemblyPublicNonGenericClasses( Assembly.GetAssembly(typeof(ICheckFixCacheValuesService)), Assembly.GetAssembly(typeof(BookListDto)), Assembly.GetAssembly(typeof(IBookToCosmosBookService)), Assembly.GetAssembly(typeof(IBookGenerator)), Assembly.GetAssembly(typeof(IPlaceOrderBizLogic)), Assembly.GetAssembly(typeof(IPlaceOrderDbAccess)), Assembly.GetAssembly(typeof(IListBooksCachedService)), Assembly.GetAssembly(typeof(ICosmosEfListNoSqlBooksService)), Assembly.GetAssembly(typeof(IListBooksService)), Assembly.GetAssembly(typeof(IDisplayOrdersService)), Assembly.GetAssembly(typeof(IListUdfsBooksService)), Assembly.GetAssembly(typeof(IListUdfsBooksService)) ) .AsPublicImplementedInterfaces(); services.AddHostedService <CheckFixCacheBackground>(); //Register EfCore.GenericEventRunner var eventConfig = new GenericEventRunnerConfig { NotUsingDuringSaveHandlers = cosmosSettings == null //This stops any attempts to update cosmos db if not turned on }; eventConfig.RegisterSaveChangesExceptionHandler <BookDbContext>(BookWithEventsConcurrencyHandler.HandleCacheValuesConcurrency); eventConfig.AddActionToRunAfterDetectChanges <BookDbContext>(BookDetectChangesExtensions.ChangeChecker); var logs = services.RegisterGenericEventRunner(eventConfig, Assembly.GetAssembly(typeof(ReviewAddedHandler)), //SQL cached values event handlers Assembly.GetAssembly(typeof(BookChangeHandlerAsync)) //Cosmos Db event handlers ); //Register EfCoreGenericServices services.ConfigureGenericServicesEntities(typeof(BookDbContext), typeof(OrderDbContext)) .ScanAssemblesForDtos( Assembly.GetAssembly(typeof(BookListDto)), Assembly.GetAssembly(typeof(AddReviewDto)) ).RegisterGenericServices(); var softLogs = services.RegisterSoftDelServicesAndYourConfigurations(); }