From fe04bd8cd5d8663933ba0401aee157112ef87b2f Mon Sep 17 00:00:00 2001 From: "Collin M. Barrett" Date: Sat, 20 Jan 2018 18:58:43 -0600 Subject: [PATCH] filter primary keys from updates, other cleanup per: https://stackoverflow.com/a/48361472/2343739 --- src/FilterLists.Data/FilterLists.Data.csproj | 1 - .../FilterListsDbContextExtensions.cs | 96 +++++++++---------- 2 files changed, 44 insertions(+), 53 deletions(-) diff --git a/src/FilterLists.Data/FilterLists.Data.csproj b/src/FilterLists.Data/FilterLists.Data.csproj index cd7900813..599cfba3e 100644 --- a/src/FilterLists.Data/FilterLists.Data.csproj +++ b/src/FilterLists.Data/FilterLists.Data.csproj @@ -6,7 +6,6 @@ - diff --git a/src/FilterLists.Data/FilterListsDbContextExtensions.cs b/src/FilterLists.Data/FilterListsDbContextExtensions.cs index f80f78a06..0b127a812 100644 --- a/src/FilterLists.Data/FilterListsDbContextExtensions.cs +++ b/src/FilterLists.Data/FilterListsDbContextExtensions.cs @@ -1,11 +1,11 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using FilterLists.Data.Entities; -using Humanizer; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Newtonsoft.Json; @@ -28,29 +28,29 @@ public static void EnsureSeeded(this FilterListsDbContext context) SeedEntities(context); //InsertOnDuplicateKeyUpdateEntities(context); SeedJunctions(context); - //TODO: determine if InsertOnDuplicateKeyUpdateEntities() will work for junctions + //TODO: determine if InsertOnDuplicateKeyUpdate() will work for junctions } private static void SeedEntities(DbContext context) { - Seed(context); - Seed(context); - Seed(context); - Seed(context); - Seed(context); - Seed(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); } private static void SeedJunctions(DbContext context) { - Seed(context); - Seed(context); - Seed(context); - Seed(context); - Seed(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); + SeedIfEmpty(context); } - private static void Seed(DbContext dbContext) where TEntity : class + private static void SeedIfEmpty(DbContext dbContext) where TEntity : class { if (dbContext.Set().Any()) return; var rows = GetSeedRows(); @@ -58,10 +58,10 @@ private static void Seed(DbContext dbContext) where TEntity : class dbContext.SaveChanges(); } - private static List GetSeedRows() + private static List GetSeedRows() { - return JsonConvert.DeserializeObject>( - File.ReadAllText(SeedDirectory + Path.DirectorySeparatorChar + typeof(TEntity).Name + ".json")); + return JsonConvert.DeserializeObject>( + File.ReadAllText(SeedDirectory + Path.DirectorySeparatorChar + typeof(TEntityType).Name + ".json")); } private static void InsertOnDuplicateKeyUpdateEntities(DbContext context) @@ -74,58 +74,50 @@ private static void InsertOnDuplicateKeyUpdateEntities(DbContext context) InsertOnDuplicateKeyUpdate(context); } - private static void InsertOnDuplicateKeyUpdate(DbContext dbContext) where TEntity : class + private static void InsertOnDuplicateKeyUpdate(DbContext dbContext) where TEntityType : class { - var columnProperties = GetColumnPropertiesLessBaseEntityTimestamps(); - var tableName = GetTableName(); - var columns = string.Join(", ", columnProperties.Select(x => x.Name)); - var values = CreateValues(columnProperties); - var updates = CreateUpdates(columnProperties); - var rawSqlString = "INSERT INTO " + tableName + " (" + columns + ") VALUES " + values + - " ON DUPLICATE KEY UPDATE " + updates; - dbContext.Set().FromSql(rawSqlString); + var entityType = dbContext.Model.FindEntityType(typeof(TEntityType)); + var properties = GetPropertiesLessValueGeneratedTimestamps(entityType); + var columns = string.Join(", ", properties.Select(x => x.Name)); + var values = CreateValues(properties); + var updates = CreateUpdates(properties); + var rawSqlString = "INSERT INTO " + entityType.Relational().TableName + " (" + columns + ") VALUES " + + values + " ON DUPLICATE KEY UPDATE " + updates; + dbContext.Set().FromSql(rawSqlString); dbContext.SaveChanges(); } - private static string GetTableName() + private static List GetPropertiesLessValueGeneratedTimestamps(IEntityType entityType) { - return typeof(TEntity).Name.Pluralize().ToLower(); + return entityType.GetProperties() + .Where(x => x.ClrType != typeof(DateTime) || x.ValueGenerated == ValueGenerated.Never).ToList(); } - private static List GetColumnPropertiesLessBaseEntityTimestamps() + private static string CreateValues(IReadOnlyCollection columnProperties) { - return typeof(TEntity).GetProperties().Where(x => - x.PropertyType.Namespace != "System.Collections.Generic" && - !new List {"CreatedDateUtc", "ModifiedDateUtc"}.Contains(x.Name)).ToList(); - } - - private static string CreateValues(IReadOnlyCollection columnProperties) - { - return GetSeedRows().Select(row => CreateRowValues(columnProperties, row)).Aggregate("", + return GetSeedRows().Select(row => CreateRowValues(columnProperties, row)).Aggregate("", (current, rowValues) => current == "" ? rowValues : current + ", " + rowValues); } - private static string CreateRowValues(IEnumerable columnProperties, TEntity row) + private static string CreateRowValues(IEnumerable properties, TEntityType row) { - return (from property in columnProperties + return (from property in properties let value = row.GetType().GetProperty(property.Name).GetValue(row) - select WrapStringPropertyValueInSingleQuotes(property, value)).Aggregate("", - (current, value) => current == "" ? "(" + value : current + ", " + value) + ")"; + select WrapStringValueInSingleQuotes(property, value)).Aggregate("", + (rowValues, value) => rowValues == "" ? "(" + value : rowValues + ", " + value) + ")"; } - private static object WrapStringPropertyValueInSingleQuotes(PropertyInfo property, object value) + private static object WrapStringValueInSingleQuotes(IProperty property, object value) { - if (property.PropertyType == typeof(string)) - value = "'" + value + "'"; - return value; + return property.ClrType == typeof(string) ? "'" + value + "'" : value; } - private static string CreateUpdates(IEnumerable columnProperties) + private static string CreateUpdates(IEnumerable properties) { - //TODO: filter keys out - return columnProperties.Select(property => property.Name).Aggregate("", (current, column) => current == "" - ? column + " = VALUES(" + column + ")" - : current + ", " + column + " = VALUES(" + column + ")"); + return (from property in properties + where !property.IsPrimaryKey() + select property.Name + " = VALUES(" + property.Name + ")").Aggregate("", + (updates, columnUpdates) => updates == "" ? columnUpdates : updates + ", " + columnUpdates); } } } \ No newline at end of file