From 12f876e95887708fc39db8de7e48673adb2fe542 Mon Sep 17 00:00:00 2001 From: Collin Barrett Date: Sun, 21 Jan 2018 20:19:37 -0600 Subject: [PATCH] finish IODKU method, Insert is wip --- FilterLists.sln.DotSettings | 1 + src/FilterLists.Api/Startup.cs | 2 +- .../FilterListsDbContextExtensions.cs | 96 +++++++++---------- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/FilterLists.sln.DotSettings b/FilterLists.sln.DotSettings index 2c4f3c460..c6d6a679f 100644 --- a/FilterLists.sln.DotSettings +++ b/FilterLists.sln.DotSettings @@ -2,6 +2,7 @@ xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> + False <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> \ No newline at end of file diff --git a/src/FilterLists.Api/Startup.cs b/src/FilterLists.Api/Startup.cs index 34b34f5cb..7d20b9352 100644 --- a/src/FilterLists.Api/Startup.cs +++ b/src/FilterLists.Api/Startup.cs @@ -50,7 +50,7 @@ private static void MigrateAndSeedDatabase(IApplicationBuilder app) using (var serviceScope = app.ApplicationServices.GetRequiredService().CreateScope()) { serviceScope.ServiceProvider.GetService().Database.Migrate(); - serviceScope.ServiceProvider.GetService().EnsureSeeded(); + serviceScope.ServiceProvider.GetService().SeedOrUpdate(); } } } diff --git a/src/FilterLists.Data/FilterListsDbContextExtensions.cs b/src/FilterLists.Data/FilterListsDbContextExtensions.cs index b01d162fc..78e6467b8 100644 --- a/src/FilterLists.Data/FilterListsDbContextExtensions.cs +++ b/src/FilterLists.Data/FilterListsDbContextExtensions.cs @@ -15,66 +15,40 @@ public static class FilterListsDbContextExtensions { private const string SeedDirectory = "Seed"; - public static bool AllMigrationsApplied(this FilterListsDbContext filterListsDbContext) + public static bool AllMigrationsApplied(this FilterListsDbContext dbContext) { - var appliedMigrationIds = filterListsDbContext.GetService().GetAppliedMigrations() + var appliedMigrationIds = dbContext.GetService().GetAppliedMigrations() .Select(m => m.MigrationId); - var allMigrationKeys = filterListsDbContext.GetService().Migrations.Select(m => m.Key); + var allMigrationKeys = dbContext.GetService().Migrations.Select(m => m.Key); return !allMigrationKeys.Except(appliedMigrationIds).Any(); } - public static void EnsureSeeded(this FilterListsDbContext filterListsDbContext) + public static void SeedOrUpdate(this FilterListsDbContext dbContext) { - SeedEntities(filterListsDbContext); - //InsertOnDuplicateKeyUpdateEntities(filterListsDbContext); - SeedJunctions(filterListsDbContext); - //TODO: determine if InsertOnDuplicateKeyUpdate() will work for junctions + PerformEntityInsertOnDuplicateKeyUpdates(dbContext); + //PerformEntityInserts(dbContext); } - private static void SeedEntities(DbContext dbContext) + private static void PerformEntityInsertOnDuplicateKeyUpdates(DbContext dbContext) { - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); + dbContext.InsertOnDuplicateKeyUpdate(); + dbContext.InsertOnDuplicateKeyUpdate(); + dbContext.InsertOnDuplicateKeyUpdate(); + dbContext.InsertOnDuplicateKeyUpdate(); + dbContext.InsertOnDuplicateKeyUpdate(); + dbContext.InsertOnDuplicateKeyUpdate(); } - private static void SeedJunctions(DbContext dbContext) + private static void PerformEntityInserts(DbContext dbContext) { - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); - SeedIfEmpty(dbContext); + dbContext.Insert(); + dbContext.Insert(); + dbContext.Insert(); + dbContext.Insert(); + dbContext.Insert(); } - private static void SeedIfEmpty(DbContext dbContext) where TEntity : class - { - if (dbContext.Set().Any()) return; - var rows = GetSeedRows(); - dbContext.AddRange(rows); - dbContext.SaveChanges(); - } - - private static List GetSeedRows() - { - return JsonConvert.DeserializeObject>( - File.ReadAllText(SeedDirectory + Path.DirectorySeparatorChar + typeof(TEntityType).Name + ".json")); - } - - private static void InsertOnDuplicateKeyUpdateEntities(DbContext dbContext) - { - InsertOnDuplicateKeyUpdate(dbContext); - InsertOnDuplicateKeyUpdate(dbContext); - InsertOnDuplicateKeyUpdate(dbContext); - InsertOnDuplicateKeyUpdate(dbContext); - InsertOnDuplicateKeyUpdate(dbContext); - InsertOnDuplicateKeyUpdate(dbContext); - } - - private static void InsertOnDuplicateKeyUpdate(DbContext dbContext) where TEntityType : class + private static void InsertOnDuplicateKeyUpdate(this DbContext dbContext) where TEntityType : class { var entityType = dbContext.Model.FindEntityType(typeof(TEntityType)); var properties = GetPropertiesLessValueGeneratedTimestamps(entityType); @@ -83,7 +57,7 @@ private static void InsertOnDuplicateKeyUpdate(DbContext dbContext) var updates = CreateUpdates(properties); var rawSqlString = "INSERT INTO " + entityType.Relational().TableName + " (" + columns + ") VALUES " + values + " ON DUPLICATE KEY UPDATE " + updates; - dbContext.Set().FromSql(rawSqlString); + dbContext.Database.ExecuteSqlCommand(rawSqlString); dbContext.SaveChanges(); } @@ -99,17 +73,31 @@ private static string CreateValues(IReadOnlyCollection p (current, rowValues) => current == "" ? rowValues : current + ", " + rowValues); } + private static List GetSeedRows() + { + return JsonConvert.DeserializeObject>( + File.ReadAllText(SeedDirectory + Path.DirectorySeparatorChar + typeof(TEntityType).Name + ".json")); + } + private static string CreateRowValues(IEnumerable properties, TEntityType row) { return (from property in properties let value = row.GetType().GetProperty(property.Name).GetValue(row) - select WrapStringValueInSingleQuotes(property, value)).Aggregate("", + select FormatDataForMySql(property, value)).Aggregate("", (rowValues, value) => rowValues == "" ? "(" + value : rowValues + ", " + value) + ")"; } - private static object WrapStringValueInSingleQuotes(IProperty property, object value) + //TODO: use .NET, EF, or other library rather than maintaining this + private static object FormatDataForMySql(IProperty property, object value) { - return property.ClrType == typeof(string) ? "'" + value + "'" : value; + if (value == null) return "NULL"; + if (property.ClrType == typeof(string)) + return "'" + value.ToString().Replace("'", "''") + "'"; + if (property.ClrType == typeof(bool)) + return Convert.ToInt32(value); + if (property.ClrType == typeof(DateTime?)) + return "'" + ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss") + "'"; + return value; } private static string CreateUpdates(IEnumerable properties) @@ -119,5 +107,13 @@ private static string CreateUpdates(IEnumerable properties) select property.Name + " = VALUES(" + property.Name + ")").Aggregate("", (updates, columnUpdates) => updates == "" ? columnUpdates : updates + ", " + columnUpdates); } + + private static void Insert(this DbContext dbContext) where TEntityType : class + { + var rows = GetSeedRows(); + //TODO: filter out pre-existing records + dbContext.Set().AddRange(rows); + dbContext.SaveChanges(); + } } } \ No newline at end of file