From 32ecac3d58749c548eecd20478c282b981a7aea9 Mon Sep 17 00:00:00 2001 From: DarkXoro Date: Tue, 9 Mar 2021 16:11:36 +0500 Subject: [PATCH 01/23] Updated to 5.0 - Also removed Newtonsoft.Json - Updated sample project to use 5.0 - Auto migrate database for sample project on creation --- AutoHistory.sln | 18 +++---- .../AspNetCore5.0.MVC.EF.Blogs.csproj} | 6 +-- .../Controllers/BlogsController.cs | 0 .../20181226223513_Initial.Designer.cs | 0 .../Migrations/20181226223513_Initial.cs | 0 .../BloggingContextModelSnapshot.cs | 0 .../Models/ErrorViewModel.cs | 0 .../Models/Model.cs | 0 .../Program.cs | 11 ++-- .../Properties/launchSettings.json | 0 .../Startup.cs | 12 ++++- .../Views/Blogs/Create.cshtml | 0 .../Views/Blogs/Delete.cshtml | 0 .../Views/Blogs/Details.cshtml | 0 .../Views/Blogs/Edit.cshtml | 0 .../Views/Blogs/Index.cshtml | 0 .../Views/Shared/Error.cshtml | 0 .../Views/Shared/_CookieConsentPartial.cshtml | 0 .../Views/Shared/_Layout.cshtml | 0 .../Shared/_ValidationScriptsPartial.cshtml | 0 .../Views/_ViewImports.cshtml | 0 .../Views/_ViewStart.cshtml | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../wwwroot/css/site.css | 0 .../wwwroot/favicon.ico | Bin .../wwwroot/js/site.js | 0 .../wwwroot/lib/bootstrap/LICENSE | 0 .../lib/bootstrap/dist/css/bootstrap-grid.css | 0 .../bootstrap/dist/css/bootstrap-grid.css.map | 0 .../bootstrap/dist/css/bootstrap-grid.min.css | 0 .../dist/css/bootstrap-grid.min.css.map | 0 .../bootstrap/dist/css/bootstrap-reboot.css | 0 .../dist/css/bootstrap-reboot.css.map | 0 .../dist/css/bootstrap-reboot.min.css | 0 .../dist/css/bootstrap-reboot.min.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.css | 0 .../lib/bootstrap/dist/css/bootstrap.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.min.css | 0 .../bootstrap/dist/css/bootstrap.min.css.map | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.js | 0 .../bootstrap/dist/js/bootstrap.bundle.js.map | 0 .../bootstrap/dist/js/bootstrap.bundle.min.js | 0 .../dist/js/bootstrap.bundle.min.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.js | 0 .../lib/bootstrap/dist/js/bootstrap.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.min.js | 0 .../bootstrap/dist/js/bootstrap.min.js.map | 0 .../jquery-validation-unobtrusive/LICENSE.txt | 0 .../jquery.validate.unobtrusive.js | 0 .../jquery.validate.unobtrusive.min.js | 0 .../wwwroot/lib/jquery-validation/LICENSE.md | 0 .../dist/additional-methods.js | 0 .../dist/additional-methods.min.js | 0 .../jquery-validation/dist/jquery.validate.js | 0 .../dist/jquery.validate.min.js | 0 .../wwwroot/lib/jquery/LICENSE.txt | 0 .../wwwroot/lib/jquery/dist/jquery.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.map | 0 .../AutoHistoryOptions.cs | 18 ------- .../Extensions/DbContextExtensions.cs | 50 ++++++++---------- .../Extensions/ModelBuilderExtensions.cs | 3 -- .../Internal/EntityContractResolver.cs | 32 ----------- ...oft.EntityFrameworkCore.AutoHistory.csproj | 7 ++- ...ntityFrameworkCore.AutoHistory.Test.csproj | 11 ++-- 66 files changed, 60 insertions(+), 108 deletions(-) rename samples/{AspNetCore2.2.MVC.EF.Blogs/AspNetCore2.2.MVC.EF.Blogs.csproj => AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj} (70%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Controllers/BlogsController.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Migrations/20181226223513_Initial.Designer.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Migrations/20181226223513_Initial.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Migrations/BloggingContextModelSnapshot.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Models/ErrorViewModel.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Models/Model.cs (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Program.cs (61%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Properties/launchSettings.json (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Startup.cs (81%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Blogs/Create.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Blogs/Delete.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Blogs/Details.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Blogs/Edit.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Blogs/Index.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Shared/Error.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Shared/_CookieConsentPartial.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Shared/_Layout.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/Shared/_ValidationScriptsPartial.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/_ViewImports.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/Views/_ViewStart.cshtml (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/appsettings.Development.json (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/appsettings.json (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/css/site.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/favicon.ico (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/js/site.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/LICENSE (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/LICENSE.md (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/additional-methods.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/additional-methods.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/jquery.validate.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery/LICENSE.txt (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.min.js (100%) rename samples/{AspNetCore2.2.MVC.EF.Blogs => AspNetCore5.0.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.min.map (100%) delete mode 100644 src/Microsoft.EntityFrameworkCore.AutoHistory/Internal/EntityContractResolver.cs diff --git a/AutoHistory.sln b/AutoHistory.sln index fd9d121..dec2726 100644 --- a/AutoHistory.sln +++ b/AutoHistory.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26228.4 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EEF95A1B-E224-4488-91ED-4CC4EC3CEEE3}" EndProject @@ -18,9 +18,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{DAEF4300-2306-4680-A609-86F2F9E4513A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{1C12ACF7-CF58-460C-8EF3-2349D8E62AC1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetCore2.2.MVC.EF.Blogs", "samples\AspNetCore2.2.MVC.EF.Blogs\AspNetCore2.2.MVC.EF.Blogs.csproj", "{AB1074C0-4529-44F0-B837-07E34AB9B321}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetCore5.0.MVC.EF.Blogs", "samples\AspNetCore5.0.MVC.EF.Blogs\AspNetCore5.0.MVC.EF.Blogs.csproj", "{01180CD5-4F4E-4C51-9478-00090C03FE73}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -36,10 +36,10 @@ Global {2F6C239E-9F05-4654-936B-CFBB00412E4B}.Debug|Any CPU.Build.0 = Debug|Any CPU {2F6C239E-9F05-4654-936B-CFBB00412E4B}.Release|Any CPU.ActiveCfg = Release|Any CPU {2F6C239E-9F05-4654-936B-CFBB00412E4B}.Release|Any CPU.Build.0 = Release|Any CPU - {AB1074C0-4529-44F0-B837-07E34AB9B321}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB1074C0-4529-44F0-B837-07E34AB9B321}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB1074C0-4529-44F0-B837-07E34AB9B321}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB1074C0-4529-44F0-B837-07E34AB9B321}.Release|Any CPU.Build.0 = Release|Any CPU + {01180CD5-4F4E-4C51-9478-00090C03FE73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01180CD5-4F4E-4C51-9478-00090C03FE73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01180CD5-4F4E-4C51-9478-00090C03FE73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01180CD5-4F4E-4C51-9478-00090C03FE73}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -47,7 +47,7 @@ Global GlobalSection(NestedProjects) = preSolution {5927DE0F-FA62-4B71-8AAF-2B3DDC405E34} = {EEF95A1B-E224-4488-91ED-4CC4EC3CEEE3} {2F6C239E-9F05-4654-936B-CFBB00412E4B} = {504C6707-0D9C-4FA7-861D-B1A97AF39E32} - {AB1074C0-4529-44F0-B837-07E34AB9B321} = {DAEF4300-2306-4680-A609-86F2F9E4513A} + {01180CD5-4F4E-4C51-9478-00090C03FE73} = {1C12ACF7-CF58-460C-8EF3-2349D8E62AC1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {ED8B7FB1-308D-49C1-8124-E03D7D6E6D85} diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/AspNetCore2.2.MVC.EF.Blogs.csproj b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj similarity index 70% rename from samples/AspNetCore2.2.MVC.EF.Blogs/AspNetCore2.2.MVC.EF.Blogs.csproj rename to samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj index 46b3c03..7b9eda8 100644 --- a/samples/AspNetCore2.2.MVC.EF.Blogs/AspNetCore2.2.MVC.EF.Blogs.csproj +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj @@ -1,12 +1,12 @@  - netcoreapp3.1 - InProcess + netcoreapp5.0 + - + diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Controllers/BlogsController.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Controllers/BlogsController.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Models/ErrorViewModel.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ErrorViewModel.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Models/ErrorViewModel.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Models/ErrorViewModel.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Models/Model.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Models/Model.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Program.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Program.cs similarity index 61% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Program.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Program.cs index 0d333cf..1d9e98a 100644 --- a/samples/AspNetCore2.2.MVC.EF.Blogs/Program.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Program.cs @@ -7,15 +7,14 @@ public class Program { public static void Main(string[] args) { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { - webBuilder.ConfigureKestrel(serverOptions => - { - // Set properties and call methods on options - }) - .UseStartup(); + webBuilder.UseStartup(); }); - } } } diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Properties/launchSettings.json b/samples/AspNetCore5.0.MVC.EF.Blogs/Properties/launchSettings.json similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Properties/launchSettings.json rename to samples/AspNetCore5.0.MVC.EF.Blogs/Properties/launchSettings.json diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Startup.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Startup.cs similarity index 81% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Startup.cs rename to samples/AspNetCore5.0.MVC.EF.Blogs/Startup.cs index 9139941..2775b29 100644 --- a/samples/AspNetCore2.2.MVC.EF.Blogs/Startup.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Startup.cs @@ -26,9 +26,9 @@ public void ConfigureServices(IServiceCollection services) options.MinimumSameSitePolicy = SameSiteMode.None; }); - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0); + services.AddControllersWithViews(); - var connection = @"Server=(local);Database=AutoHistoryTest;Trusted_Connection=True;ConnectRetryCount=0"; + var connection = @"Server=.;Database=AutoHistoryTest;Trusted_Connection=True;ConnectRetryCount=0"; services.AddDbContext(options => { options.UseSqlServer(connection); @@ -53,10 +53,18 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseStaticFiles(); app.UseCookiePolicy(); + app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute(); }); + + // only runs once at system startup + using (var scope = app.ApplicationServices.CreateScope()) + { + var db = scope.ServiceProvider.GetRequiredService(); + db.Database.Migrate(); + } } } } diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Create.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Create.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Delete.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Delete.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Details.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Details.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Edit.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Edit.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Index.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Blogs/Index.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/Error.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/Error.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/Error.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/Error.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_Layout.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_Layout.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_Layout.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_Layout.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/_ViewImports.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewImports.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/_ViewImports.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewImports.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/Views/_ViewStart.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewStart.cshtml similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/Views/_ViewStart.cshtml rename to samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewStart.cshtml diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/appsettings.Development.json b/samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.Development.json similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/appsettings.Development.json rename to samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.Development.json diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/appsettings.json b/samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.json similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/appsettings.json rename to samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.json diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/css/site.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/css/site.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/css/site.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/css/site.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/favicon.ico b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/favicon.ico similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/favicon.ico rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/favicon.ico diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/js/site.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/js/site.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/js/site.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/js/site.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js diff --git a/samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map b/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map similarity index 100% rename from samples/AspNetCore2.2.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map rename to samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs index 6239dc2..5f1ea2a 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; namespace Microsoft.EntityFrameworkCore.Internal { @@ -45,21 +43,5 @@ private AutoHistoryOptions() /// The max length for the table column. Default: 128. /// public int TableMaxLength { get; set; } = 128; - - /// - /// The JsonSerializerSettings for the changed column. - /// - public JsonSerializerSettings JsonSerializerSettings { get; set; } = new JsonSerializerSettings() - { - ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - ContractResolver = new CamelCasePropertyNamesContractResolver(), - Formatting = Formatting.None, - NullValueHandling = NullValueHandling.Ignore - }; - - /// - /// The json serializer to use when writing changes. Created internally. - /// - internal JsonSerializer JsonSerializer { get; set; } } } diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index a4cde84..0ecb5a7 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -3,12 +3,10 @@ using System; using System.Collections.Generic; using System.Linq; - +using System.Text.Json; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Internal; -using Newtonsoft.Json.Linq; - namespace Microsoft.EntityFrameworkCore { /// @@ -47,9 +45,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F // (include shadow properties, not include navigations & references) var properties = entry.Properties; - var formatting = AutoHistoryOptions.Instance.JsonSerializerSettings.Formatting; - var jsonSerializer = AutoHistoryOptions.Instance.JsonSerializer; - var json = new JObject(); + dynamic json = new System.Dynamic.ExpandoObject(); switch (entry.State) { case EntityState.Added: @@ -59,19 +55,19 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F { continue; } - json[prop.Metadata.Name] = prop.CurrentValue != null - ? JToken.FromObject(prop.CurrentValue, jsonSerializer) - : JValue.CreateNull(); + ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue != null + ? prop.CurrentValue + : null; } // REVIEW: what's the best way to set the RowId? history.RowId = "0"; history.Kind = EntityState.Added; - history.Changed = json.ToString(formatting); + history.Changed = JsonSerializer.Serialize(json); break; case EntityState.Modified: - var bef = new JObject(); - var aft = new JObject(); + dynamic bef = new System.Dynamic.ExpandoObject(); + dynamic aft = new System.Dynamic.ExpandoObject(); PropertyValues databaseValues = null; foreach (var prop in properties) @@ -82,45 +78,45 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F { if (!prop.OriginalValue.Equals(prop.CurrentValue)) { - bef[prop.Metadata.Name] = JToken.FromObject(prop.OriginalValue, jsonSerializer); + ((IDictionary)bef)[prop.Metadata.Name] = prop.OriginalValue; } else { databaseValues = databaseValues ?? entry.GetDatabaseValues(); var originalValue = databaseValues.GetValue(prop.Metadata.Name); - bef[prop.Metadata.Name] = originalValue != null - ? JToken.FromObject(originalValue, jsonSerializer) - : JValue.CreateNull(); + ((IDictionary)bef)[prop.Metadata.Name] = originalValue != null + ? originalValue + : null; } } else { - bef[prop.Metadata.Name] = JValue.CreateNull(); + ((IDictionary)bef)[prop.Metadata.Name] = null; } - aft[prop.Metadata.Name] = prop.CurrentValue != null - ? JToken.FromObject(prop.CurrentValue, jsonSerializer) - : JValue.CreateNull(); + ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue != null + ? prop.CurrentValue + : null; } } - json["before"] = bef; - json["after"] = aft; + ((IDictionary)json)["before"] = bef; + ((IDictionary)json)["after"] = aft; history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Modified; - history.Changed = json.ToString(formatting); + history.Changed = JsonSerializer.Serialize(json); break; case EntityState.Deleted: foreach (var prop in properties) { - json[prop.Metadata.Name] = prop.OriginalValue != null - ? JToken.FromObject(prop.OriginalValue, jsonSerializer) - : JValue.CreateNull(); + ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue != null + ? prop.OriginalValue + : null; } history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Deleted; - history.Changed = json.ToString(formatting); + history.Changed = JsonSerializer.Serialize(json); break; case EntityState.Detached: case EntityState.Unchanged: diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs index 9b8540d..4a0b42e 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs @@ -2,8 +2,6 @@ using System; using Microsoft.EntityFrameworkCore.Internal; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; namespace Microsoft.EntityFrameworkCore { @@ -34,7 +32,6 @@ public static ModelBuilder EnableAutoHistory(this ModelBuilder mod { var options = AutoHistoryOptions.Instance; configure?.Invoke(options); - options.JsonSerializer = JsonSerializer.Create(options.JsonSerializerSettings); modelBuilder.Entity(b => { diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Internal/EntityContractResolver.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Internal/EntityContractResolver.cs deleted file mode 100644 index e767f46..0000000 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Internal/EntityContractResolver.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Arch team. All rights reserved. - -using System; -using System.Collections.Generic; -using System.Linq; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; - -namespace Microsoft.EntityFrameworkCore.Internal { - internal class EntityContractResolver : DefaultContractResolver { - private readonly DbContext _dbContext; - - public EntityContractResolver(DbContext dbContext) { - _dbContext = dbContext; - } - - protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) { - var list = base.CreateProperties(type, memberSerialization); - - var entry = _dbContext.ChangeTracker.Entries().FirstOrDefault(e => e.Entity.GetType() == type); - if (entry == null) { - return list; - } - - // Get the navigations - var navigations = entry.Metadata.GetNavigations().Select(n => n.Name); - - // Exclude the navigation properties - return list.Where(p => !navigations.Contains(p.PropertyName)).ToArray(); - } - } -} diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj index c816fc6..9afcdff 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj @@ -1,9 +1,9 @@  A plugin for Microsoft.EntityFrameworkCore to support automatically recording data changes history. - 3.1.3 + 5.0.0 rigofunc;rigofunc@outlook.com - netstandard2.0 + net5.0 $(NoWarn);CS1591 true true @@ -16,7 +16,6 @@ https://github.com/arch/AutoHistory.git - - + \ No newline at end of file diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj index 41ec7d6..c7c6e8d 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj @@ -1,6 +1,6 @@  - netcoreapp3.1 + netcoreapp5.0 $(NoWarn);CS1591 true Microsoft.EntityFrameworkCore.AutoHistory.Test @@ -8,9 +8,12 @@ true - - - + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 6b7621a8dfc07047f3d6919adea25726b3ea87fc Mon Sep 17 00:00:00 2001 From: Norman Panzer Date: Fri, 26 Mar 2021 23:47:35 +0100 Subject: [PATCH 02/23] Extended DbContextExtensions with "EnsureAddedHistory". Usage Example: var addedEntries = this.ChangeTracker .Entries() .Where(e => e.State == EntityState.Added) .ToArray(); dbContext.EnsureAutoHistory(); dbContext.SaveChanges(); dbContext.EnsureAddedHistory(addedEntries); dbContext.SaveChanges(); --- .../Extensions/DbContextExtensions.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index 0ecb5a7..3a1a134 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -127,6 +127,60 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F return history; } + /// + /// Ensures the history for added entries + /// + /// + /// + public static void EnsureAddedHistory( + this DbContext context, + EntityEntry[] addedEntries) + { + EnsureAddedHistory( + context, + () => new AutoHistory(), + addedEntries); + } + + public static void EnsureAddedHistory( + this DbContext context, + Func createHistoryFactory, + EntityEntry[] addedEntries) + where TAutoHistory : AutoHistory + { + foreach (var entry in addedEntries) + { + context.Add(entry.AddedHistory(createHistoryFactory)); + } + } + + internal static TAutoHistory AddedHistory( + this EntityEntry entry, + Func createHistoryFactory) + where TAutoHistory : AutoHistory + { + var history = createHistoryFactory(); + history.TableName = entry.Metadata + .GetTableName(); + + // Get the mapped properties for the entity type. + // (include shadow properties, not include navigations & references) + var properties = entry.Properties; + + dynamic json = new System.Dynamic.ExpandoObject(); + + foreach (var prop in properties) + { + ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue != null ? + prop.OriginalValue + : null; + } + history.RowId = entry.PrimaryKey(); + history.Kind = EntityState.Added; + history.Changed = JsonSerializer.Serialize(json); + return history; + } + private static string PrimaryKey(this EntityEntry entry) { var key = entry.Metadata.FindPrimaryKey(); From ba2a003277232fe7a33256f94a717e6ccf4eaec0 Mon Sep 17 00:00:00 2001 From: Fredi Kats Date: Mon, 29 Mar 2021 22:49:04 +0300 Subject: [PATCH 03/23] feat: add default value for EnableAutoHistory --- samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs | 2 +- .../Extensions/ModelBuilderExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs index 39b2bbe..dbfb5fc 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs @@ -14,7 +14,7 @@ public BloggingContext(DbContextOptions options) protected override void OnModelCreating(ModelBuilder modelBuilder) { // enable auto history functionality. - modelBuilder.EnableAutoHistory(changedMaxLength: null); + modelBuilder.EnableAutoHistory(); } } diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs index 4a0b42e..05ea68f 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs @@ -18,7 +18,7 @@ public static class ModelBuilderExtensions /// The to enable auto history feature. /// The maximum length of the 'Changed' column. null will use default setting 2048. /// The had enabled auto history feature. - public static ModelBuilder EnableAutoHistory(this ModelBuilder modelBuilder, int? changedMaxLength) + public static ModelBuilder EnableAutoHistory(this ModelBuilder modelBuilder, int? changedMaxLength = null) { return ModelBuilderExtensions.EnableAutoHistory(modelBuilder, o => { From 5d0710d31bb8ba06dac53f206280b32950c0ce61 Mon Sep 17 00:00:00 2001 From: Mohsen Esmailpour Date: Wed, 26 May 2021 20:37:24 +0430 Subject: [PATCH 04/23] Improve Readme file. --- README.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 88a2b7d..6c4a22e 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,40 @@ public class BloggingContext : DbContext } ``` -3. Ensure AutoHistory in DbContext. This must be called before bloggingContext.SaveChanges() or bloggingContext.SaveChangesAsync(). +3. Ensure AutoHistory in DbContext. This must be called before `bloggingContext.SaveChanges()` or `bloggingContext.SaveChangesAsync()`. ```csharp bloggingContext.EnsureAutoHistory() ``` +If you want to record data changes for all entities, just override `SaveChanges` and `SaveChangesAsync` methods and call `EnsureAutoHistory()` inside overridden version: +```csharp +public class BloggingContext : DbContext +{ + public BloggingContext(DbContextOptions options) + : base(options) + { } + + public override int SaveChanges() + { + this.EnsureAutoHistory(); + return base.SaveChanges(); + } + + public override Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) + { + this.EnsureAutoHistory(); + return base.SaveChangesAsync(cancellationToken); + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + // enable auto history functionality. + modelBuilder.EnableAutoHistory(); + } +} +``` + # Use Custom AutoHistory Entity You can use a custom auto history entity by extending the Microsoft.EntityFrameworkCore.AutoHistory class. From fb6c03041bb5d92f80243df034f7d093562fd561 Mon Sep 17 00:00:00 2001 From: Mohsen Esmailpour Date: Wed, 26 May 2021 20:54:42 +0430 Subject: [PATCH 05/23] Remove extra null checks --- .../Extensions/DbContextExtensions.cs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index 0ecb5a7..023b910 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -55,9 +55,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F { continue; } - ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue != null - ? prop.CurrentValue - : null; + ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue; } // REVIEW: what's the best way to set the RowId? @@ -82,11 +80,9 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F } else { - databaseValues = databaseValues ?? entry.GetDatabaseValues(); + databaseValues ??= entry.GetDatabaseValues(); var originalValue = databaseValues.GetValue(prop.Metadata.Name); - ((IDictionary)bef)[prop.Metadata.Name] = originalValue != null - ? originalValue - : null; + ((IDictionary)bef)[prop.Metadata.Name] = originalValue; } } else @@ -94,9 +90,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F ((IDictionary)bef)[prop.Metadata.Name] = null; } - ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue != null - ? prop.CurrentValue - : null; + ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue; } } @@ -110,9 +104,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F case EntityState.Deleted: foreach (var prop in properties) { - ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue != null - ? prop.OriginalValue - : null; + ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue; } history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Deleted; From b0c22e35dacbb2a7b5d4d36d870c3c91e15eae53 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 5 Jul 2021 15:25:39 +0200 Subject: [PATCH 06/23] Add attribute to exclude properties from history changes using[ExcludeFromHistory]. Changed context and demo to support new "private" field Added Tests. --- .../Controllers/BlogsController.cs | 4 +- ...113831_blog_privateURLProperty.Designer.cs | 114 +++++++++++++ .../20210705113831_blog_privateURLProperty.cs | 23 +++ .../BloggingContextModelSnapshot.cs | 53 ++++-- .../Models/ContextFactory.cs | 47 ++++++ .../Models/Model.cs | 7 +- .../Views/Blogs/Create.cshtml | 5 + .../Views/Blogs/Delete.cshtml | 15 +- .../Views/Blogs/Details.cshtml | 12 +- .../Views/Blogs/Edit.cshtml | 5 + .../Views/Blogs/Index.cshtml | 6 + .../Attributes/ExcludeFromHistoryAttribute.cs | 6 + .../Extensions/DbContextExtensions.cs | 157 ++++++++++-------- .../AutoHistoryExcludePropertyTest.cs | 69 ++++++++ .../AutoHistoryGenericTest.cs | 6 +- .../AutoHistoryTest.cs | 8 +- .../BloggingContext.cs | 3 + 17 files changed, 446 insertions(+), 94 deletions(-) create mode 100644 samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs create mode 100644 samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs create mode 100644 samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs create mode 100644 src/Microsoft.EntityFrameworkCore.AutoHistory/Attributes/ExcludeFromHistoryAttribute.cs create mode 100644 test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs index dc5442c..37c82e7 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs @@ -50,7 +50,7 @@ public IActionResult Create() // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] - public async Task Create([Bind("BlogId,Url")] Blog blog) + public async Task Create([Bind("BlogId,Url,PrivateURL")] Blog blog) { if (ModelState.IsValid) { @@ -83,7 +83,7 @@ public async Task Edit(int? id) // more details see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] - public async Task Edit(int id, [Bind("BlogId,Url")] Blog blog) + public async Task Edit(int id, [Bind("BlogId,Url,PrivateURL")] Blog blog) { if (id != blog.BlogId) { diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs new file mode 100644 index 0000000..9f11724 --- /dev/null +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs @@ -0,0 +1,114 @@ +// +using System; +using EFGetStarted.AspNetCore.NewDb.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace EFGetStarted.AspNetCore.NewDb.Migrations +{ + [DbContext(typeof(BloggingContext))] + [Migration("20210705113831_blog_privateURLProperty")] + partial class blog_privateURLProperty + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.0"); + + modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Blog", b => + { + b.Property("BlogId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("PrivateURL") + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .HasColumnType("nvarchar(max)"); + + b.HasKey("BlogId"); + + b.ToTable("Blogs"); + }); + + modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("BlogId") + .HasColumnType("int"); + + b.Property("Content") + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .HasColumnType("nvarchar(max)"); + + b.HasKey("PostId"); + + b.HasIndex("BlogId"); + + b.ToTable("Posts"); + }); + + modelBuilder.Entity("Microsoft.EntityFrameworkCore.AutoHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .UseIdentityColumn(); + + b.Property("Changed") + .HasColumnType("nvarchar(max)"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Kind") + .HasColumnType("int"); + + b.Property("RowId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("TableName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.ToTable("AutoHistory"); + }); + + modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Post", b => + { + b.HasOne("EFGetStarted.AspNetCore.NewDb.Models.Blog", "Blog") + .WithMany("Posts") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Blog", b => + { + b.Navigation("Posts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs new file mode 100644 index 0000000..b020144 --- /dev/null +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace EFGetStarted.AspNetCore.NewDb.Migrations +{ + public partial class blog_privateURLProperty : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PrivateURL", + table: "Blogs", + type: "nvarchar(max)", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PrivateURL", + table: "Blogs"); + } + } +} diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs index f96433d..ad0d897 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs @@ -15,17 +15,22 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "2.2.0-rtm-35687") + .UseIdentityColumns() .HasAnnotation("Relational:MaxIdentifierLength", 128) - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasAnnotation("ProductVersion", "5.0.0"); modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Blog", b => { b.Property("BlogId") .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int") + .UseIdentityColumn(); - b.Property("Url"); + b.Property("PrivateURL") + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .HasColumnType("nvarchar(max)"); b.HasKey("BlogId"); @@ -36,13 +41,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("PostId") .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int") + .UseIdentityColumn(); - b.Property("BlogId"); + b.Property("BlogId") + .HasColumnType("int"); - b.Property("Content"); + b.Property("Content") + .HasColumnType("nvarchar(max)"); - b.Property("Title"); + b.Property("Title") + .HasColumnType("nvarchar(max)"); b.HasKey("PostId"); @@ -55,21 +64,27 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + .HasColumnType("int") + .UseIdentityColumn(); - b.Property("Changed"); + b.Property("Changed") + .HasColumnType("nvarchar(max)"); - b.Property("Created"); + b.Property("Created") + .HasColumnType("datetime2"); - b.Property("Kind"); + b.Property("Kind") + .HasColumnType("int"); b.Property("RowId") .IsRequired() - .HasMaxLength(50); + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); b.Property("TableName") .IsRequired() - .HasMaxLength(128); + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); b.HasKey("Id"); @@ -81,7 +96,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasOne("EFGetStarted.AspNetCore.NewDb.Models.Blog", "Blog") .WithMany("Posts") .HasForeignKey("BlogId") - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("EFGetStarted.AspNetCore.NewDb.Models.Blog", b => + { + b.Navigation("Posts"); }); #pragma warning restore 612, 618 } diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs new file mode 100644 index 0000000..ca94c43 --- /dev/null +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace EFGetStarted.AspNetCore.NewDb.Models +{ + /// + /// Class need for EF Migrations to know how the Context should be created. + /// This class is not intended for use on the applications. + /// + public class BloggingContextFactory : IDesignTimeDbContextFactory + { + /// + /// Creates a DbOptionsBuilder from a connectionString. + /// + /// ConnectionString to apply. + /// DbContextOptionsBuilder. + public static DbContextOptionsBuilder CreateDbOptionsBuilder(string connectionString) + { + var options = new DbContextOptionsBuilder(); + return SetDbOptions(options, connectionString); + } + + /// + /// Set options to a DbOptionsBuilder. + /// + /// Options. + /// ConnectionString to apply. + /// DbContextOptionsBuilder. + public static DbContextOptionsBuilder SetDbOptions(DbContextOptionsBuilder options, string connectionString) + { + return options.UseSqlServer(connectionString); + } + + + /// + /// Create a new DB Context, not intended to be used. + /// + /// + /// + public BloggingContext CreateDbContext(string[] args) + { + var connection = @"Server=.;Database=AutoHistoryTest;Trusted_Connection=True;ConnectRetryCount=0"; + var optionsBuilder = CreateDbOptionsBuilder(connection); + return new BloggingContext(optionsBuilder.Options); + } + } +} diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs index dbfb5fc..88d7bc1 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs @@ -5,12 +5,14 @@ namespace EFGetStarted.AspNetCore.NewDb.Models { public class BloggingContext : DbContext { - public BloggingContext(DbContextOptions options) + public BloggingContext(DbContextOptions options) : base(options) { } public DbSet Blogs { get; set; } public DbSet Posts { get; set; } + public DbSet AutoHistory { get; set; } + protected override void OnModelCreating(ModelBuilder modelBuilder) { // enable auto history functionality. @@ -24,6 +26,9 @@ public class Blog public int BlogId { get; set; } public string Url { get; set; } + [ExcludeFromHistory] + public string PrivateURL { get; set; } + public ICollection Posts { get; set; } } diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml index 94e74b6..0066a0a 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml @@ -17,6 +17,11 @@ +
+ + + +
diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml index 2e9a3cb..92badf7 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml @@ -11,14 +11,23 @@

Blog


-
+
@Html.DisplayNameFor(model => model.Url)
-
+
@Html.DisplayFor(model => model.Url)
- + +
+
+ @Html.DisplayNameFor(model => model.PrivateURL) +
+
+ @Html.DisplayFor(model => model.PrivateURL) +
+
+
| diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml index 2b20038..0520fe7 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml @@ -10,13 +10,21 @@

Blog


-
+
@Html.DisplayNameFor(model => model.Url)
-
+
@Html.DisplayFor(model => model.Url)
+
+
+ @Html.DisplayNameFor(model => model.PrivateURL) +
+
+ @Html.DisplayFor(model => model.PrivateURL) +
+
Edit | Back to List diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml index 8e567e8..f91e117 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml @@ -18,6 +18,11 @@ +
+ + + +
diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml index 42befd3..0cad7fd 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml @@ -15,6 +15,9 @@ @Html.DisplayNameFor(model => model.Url) + + @Html.DisplayNameFor(model => model.PrivateURL) + @@ -24,6 +27,9 @@ @Html.DisplayFor(modelItem => item.Url) + + @Html.DisplayFor(modelItem => item.PrivateURL) + Edit | Details | diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Attributes/ExcludeFromHistoryAttribute.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Attributes/ExcludeFromHistoryAttribute.cs new file mode 100644 index 0000000..cb47a16 --- /dev/null +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Attributes/ExcludeFromHistoryAttribute.cs @@ -0,0 +1,6 @@ +using System; + +namespace Microsoft.EntityFrameworkCore +{ + public class ExcludeFromHistoryAttribute : Attribute { } +} diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index dd032b9..db5630c 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -31,92 +31,109 @@ public static void EnsureAutoHistory(this DbContext context, Func< var entries = context.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Deleted).ToArray(); foreach (var entry in entries) { - context.Add(entry.AutoHistory(createHistoryFactory)); + var autoHistory = entry.AutoHistory(createHistoryFactory); + if (autoHistory != null) + { + context.Add(autoHistory); + } } } internal static TAutoHistory AutoHistory(this EntityEntry entry, Func createHistoryFactory) where TAutoHistory : AutoHistory { - var history = createHistoryFactory(); - history.TableName = entry.Metadata.GetTableName(); - - // Get the mapped properties for the entity type. + // Get not excluded mapped properties for the entity type. // (include shadow properties, not include navigations & references) - var properties = entry.Properties; - dynamic json = new System.Dynamic.ExpandoObject(); - switch (entry.State) + var excludedProperties = entry.Metadata.ClrType.GetProperties() + .Where(p => p.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Count() > 0) + .Select(p => p.Name); + + var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); + //Bug: If remaining properties to check are not modified, AutoHistory still returns an object with empty changes. + + if (properties.Any(p => p.IsModified)) { - case EntityState.Added: - foreach (var prop in properties) - { - if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey()) + var history = createHistoryFactory(); + history.TableName = entry.Metadata.GetTableName(); + + dynamic json = new System.Dynamic.ExpandoObject(); + switch (entry.State) + { + case EntityState.Added: + foreach (var prop in properties) { - continue; + if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey()) + { + continue; + } + ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue; } - ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue; - } - - // REVIEW: what's the best way to set the RowId? - history.RowId = "0"; - history.Kind = EntityState.Added; - history.Changed = JsonSerializer.Serialize(json); - break; - case EntityState.Modified: - dynamic bef = new System.Dynamic.ExpandoObject(); - dynamic aft = new System.Dynamic.ExpandoObject(); - - PropertyValues databaseValues = null; - foreach (var prop in properties) - { - if (prop.IsModified) + + // REVIEW: what's the best way to set the RowId? + history.RowId = "0"; + history.Kind = EntityState.Added; + history.Changed = JsonSerializer.Serialize(json); + break; + case EntityState.Modified: + dynamic bef = new System.Dynamic.ExpandoObject(); + dynamic aft = new System.Dynamic.ExpandoObject(); + + PropertyValues databaseValues = null; + foreach (var prop in properties) { - if (prop.OriginalValue != null) + if (prop.IsModified) { - if (!prop.OriginalValue.Equals(prop.CurrentValue)) + if (prop.OriginalValue != null) { - ((IDictionary)bef)[prop.Metadata.Name] = prop.OriginalValue; + if (!prop.OriginalValue.Equals(prop.CurrentValue)) + { + ((IDictionary)bef)[prop.Metadata.Name] = prop.OriginalValue; + } + else + { + databaseValues ??= entry.GetDatabaseValues(); + var originalValue = databaseValues.GetValue(prop.Metadata.Name); + ((IDictionary)bef)[prop.Metadata.Name] = originalValue; + } } else { - databaseValues ??= entry.GetDatabaseValues(); - var originalValue = databaseValues.GetValue(prop.Metadata.Name); - ((IDictionary)bef)[prop.Metadata.Name] = originalValue; + ((IDictionary)bef)[prop.Metadata.Name] = null; } + + ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue; } - else - { - ((IDictionary)bef)[prop.Metadata.Name] = null; - } + } + + ((IDictionary)json)["before"] = bef; + ((IDictionary)json)["after"] = aft; - ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue; + history.RowId = entry.PrimaryKey(); + history.Kind = EntityState.Modified; + history.Changed = JsonSerializer.Serialize(json); + break; + case EntityState.Deleted: + foreach (var prop in properties) + { + ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue; } - } - - ((IDictionary)json)["before"] = bef; - ((IDictionary)json)["after"] = aft; - - history.RowId = entry.PrimaryKey(); - history.Kind = EntityState.Modified; - history.Changed = JsonSerializer.Serialize(json); - break; - case EntityState.Deleted: - foreach (var prop in properties) - { - ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue; - } - history.RowId = entry.PrimaryKey(); - history.Kind = EntityState.Deleted; - history.Changed = JsonSerializer.Serialize(json); - break; - case EntityState.Detached: - case EntityState.Unchanged: - default: - throw new NotSupportedException("AutoHistory only support Deleted and Modified entity."); - } + history.RowId = entry.PrimaryKey(); + history.Kind = EntityState.Deleted; + history.Changed = JsonSerializer.Serialize(json); + break; + case EntityState.Detached: + case EntityState.Unchanged: + default: + throw new NotSupportedException("AutoHistory only support Deleted and Modified entity."); + } - return history; + return history; + } + else + { + return null; + } } /// @@ -142,7 +159,11 @@ public static void EnsureAddedHistory( { foreach (var entry in addedEntries) { - context.Add(entry.AddedHistory(createHistoryFactory)); + var autoHistory = entry.AutoHistory(createHistoryFactory); + if (autoHistory != null) + { + context.Add(autoHistory); + } } } @@ -157,7 +178,11 @@ internal static TAutoHistory AddedHistory( // Get the mapped properties for the entity type. // (include shadow properties, not include navigations & references) - var properties = entry.Properties; + var excludedProperties = entry.Metadata.ClrType.GetProperties() + .Where(p => p.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Count() > 0) + .Select(p => p.Name); + + var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); dynamic json = new System.Dynamic.ExpandoObject(); diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs new file mode 100644 index 0000000..4009cfd --- /dev/null +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace Microsoft.EntityFrameworkCore.AutoHistory.Test +{ + public class AutoHistoryExcludePropertyTest + { + [Fact] + public void Entity_Update_AutoHistory_Exclude_Only_Modified_Property_Changed_Test() + { + using (var db = new BloggingContext()) + { + var blog = new Blog + { + Url = "http://blogs.msdn.com/adonet", + Posts = new List { + new Post { + Title = "xUnit", + Content = "Post from xUnit test." + } + }, + PrivateURL = "http://www.secret.com" + }; + + db.Attach(blog); + db.SaveChanges(); + + blog.PrivateURL = "http://new.secret.com"; + db.EnsureAutoHistory(); + + var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Added); + + //No changes are made (excluded is the only property modified) + Assert.Equal(0, count); + } + } + + [Fact] + public void Entity_Update_AutoHistory_Exclude_Changed_Test() + { + using (var db = new BloggingContext()) + { + var blog = new Blog + { + Url = "http://blogs.msdn.com/adonet", + Posts = new List { + new Post { + Title = "xUnit", + Content = "Post from xUnit test." + } + }, + PrivateURL = "http://www.secret.com" + }; + + db.Attach(blog); + db.SaveChanges(); + + blog.PrivateURL = "http://new.secret.com"; + blog.Posts[0].NumViews = 10; + db.EnsureAutoHistory(); + + var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Added); + + Assert.Equal(1, count); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryGenericTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryGenericTest.cs index 8e90a3c..73a4c88 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryGenericTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryGenericTest.cs @@ -19,7 +19,8 @@ public void Entity_Add_AutoHistory_Test() Title = "xUnit", Content = "Post from xUnit test." } - } + }, + PrivateURL = "http://www.secret.com" }); db.EnsureAutoHistory(() => new CustomAutoHistory() { @@ -45,7 +46,8 @@ public void Entity_Update_AutoHistory_Test() Title = "xUnit", Content = "Post from xUnit test." } - } + }, + PrivateURL = "http://www.secret.com" }; db.Attach(blog); db.SaveChanges(); diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs index 47e1880..c7e6d86 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs @@ -19,8 +19,9 @@ public void Entity_Add_AutoHistory_Test() Title = "xUnit", Content = "Post from xUnit test." } - } - }); + }, + PrivateURL = "http://www.secret.com" + }); ; db.EnsureAutoHistory(); var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Added); @@ -42,7 +43,8 @@ public void Entity_Update_AutoHistory_Test() Title = "xUnit", Content = "Post from xUnit test." } - } + }, + PrivateURL = "http://www.secret.com" }; db.Attach(blog); db.SaveChanges(); diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs index 203a606..a090ef2 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs @@ -45,6 +45,9 @@ public class Blog { public int BlogId { get; set; } public string Url { get; set; } + + [ExcludeFromHistory] + public string PrivateURL { get; set; } public List Posts { get; set; } } From 3185d71b9ee4f0a3e9c85393c3a31efe0586aecb Mon Sep 17 00:00:00 2001 From: Isaac Date: Wed, 7 Jul 2021 09:42:51 +0200 Subject: [PATCH 07/23] update readme with exluded from history attribute --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 6c4a22e..21e146d 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,18 @@ db.EnsureAutoHistory(() => new CustomAutoHistory() }); ``` +# Excluding properties from AutoHistory +You can now excluded properties from being saved into the AutoHistory tables by adding a custom attribute[ExcludeFromHistoryAttribute] attribute to your model properties. + + +```csharp + public class Blog + { + [ExcludeFromHistory] + public string PrivateURL { get; set; } + } +``` + # Integrate AutoHistory into other Package [Microsoft.EntityFrameworkCore.UnitOfWork](https://github.com/lovedotnet/UnitOfWork) had integrated this package. From 4630c333c87c5d0d747457dd4ecf65bbdbd984a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?yingtingxu=28=E5=BE=90=E5=BA=94=E5=BA=AD=29?= Date: Wed, 7 Jul 2021 17:15:37 +0800 Subject: [PATCH 08/23] deps: update deps to latest v5.0.7 --- .../AspNetCore5.0.MVC.EF.Blogs.csproj | 2 +- .../Microsoft.EntityFrameworkCore.AutoHistory.csproj | 4 ++-- .../Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj index 7b9eda8..bcdfa59 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj index 9afcdff..53b3b14 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj @@ -1,7 +1,7 @@  A plugin for Microsoft.EntityFrameworkCore to support automatically recording data changes history. - 5.0.0 + 5.0.7 rigofunc;rigofunc@outlook.com net5.0 $(NoWarn);CS1591 @@ -16,6 +16,6 @@ https://github.com/arch/AutoHistory.git - + \ No newline at end of file diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj index c7c6e8d..c13ecad 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj @@ -8,8 +8,8 @@ true - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 4555b28a346db54f8b1cc26c74a24491b144b6c5 Mon Sep 17 00:00:00 2001 From: efk2 Date: Fri, 9 Jul 2021 14:03:53 +0200 Subject: [PATCH 09/23] Extended README.md with "EnsureAddedHistory" documentation --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 21e146d..b25c941 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ public class BloggingContext : DbContext bloggingContext.EnsureAutoHistory() ``` -If you want to record data changes for all entities, just override `SaveChanges` and `SaveChangesAsync` methods and call `EnsureAutoHistory()` inside overridden version: +If you want to record data changes for all entities (except for Added - entities), just override `SaveChanges` and `SaveChangesAsync` methods and call `EnsureAutoHistory()` inside overridden version: ```csharp public class BloggingContext : DbContext { @@ -65,6 +65,31 @@ public class BloggingContext : DbContext } } ``` +4. If you also want to record Added - Entities, which is not possible per default, override `SaveChanges` and `SaveChangesAsync` methods this way: +```csharp +public class BloggingContext : DbContext +{ + public override int SaveChanges() + { + var addedEntries = this.ChangeTracker + .Entries() + .Where(e => e.State == EntityState.Added) + .ToArray(); // remember added entries, + // before EF Core is assigning valid Ids (it does on save changes, + // when ids equal zero) and setting their state to + // Unchanged (it does on every save changes) + this.EnsureAutoHistory(); + base.SaveChanges(); + + // after "SaveChanges" added enties now have gotten valid ids (if it was necessary) + // and the history for them can be ensured and be saved with another "SaveChanges" + this.EnsureAddedHistory(addedEntries); + base.SaveChanges(); + } +} +``` + + # Use Custom AutoHistory Entity You can use a custom auto history entity by extending the Microsoft.EntityFrameworkCore.AutoHistory class. From 1cf838a8d2b596d9db2bfd2df892ad9674bd49bf Mon Sep 17 00:00:00 2001 From: efk2 Date: Fri, 9 Jul 2021 16:10:41 +0200 Subject: [PATCH 10/23] README.md: corrected typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b25c941..73a71e5 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ public class BloggingContext : DbContext { public override int SaveChanges() { - var addedEntries = this.ChangeTracker + var addedEntities = this.ChangeTracker .Entries() .Where(e => e.State == EntityState.Added) .ToArray(); // remember added entries, @@ -83,7 +83,7 @@ public class BloggingContext : DbContext // after "SaveChanges" added enties now have gotten valid ids (if it was necessary) // and the history for them can be ensured and be saved with another "SaveChanges" - this.EnsureAddedHistory(addedEntries); + this.EnsureAddedHistory(addedEntities); base.SaveChanges(); } } From d2bfbc5c5bbaa6cce8ede3ecc5aee364530ce28e Mon Sep 17 00:00:00 2001 From: Felix hoi Date: Thu, 14 Oct 2021 10:43:29 +0800 Subject: [PATCH 11/23] add option for JsonSerializerOptions --- .../AutoHistoryOptions.cs | 6 ++++++ .../Extensions/DbContextExtensions.cs | 6 +++--- .../Extensions/ModelBuilderExtensions.cs | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs index 5f1ea2a..1d05c45 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/AutoHistoryOptions.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using System.Text.Json; namespace Microsoft.EntityFrameworkCore.Internal { @@ -43,5 +44,10 @@ private AutoHistoryOptions() /// The max length for the table column. Default: 128. /// public int TableMaxLength { get; set; } = 128; + + /// + /// The json setting for the 'Changed' column + /// + public JsonSerializerOptions JsonSerializerOptions; } } diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index db5630c..ee395a2 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -111,7 +111,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Modified; - history.Changed = JsonSerializer.Serialize(json); + history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); break; case EntityState.Deleted: foreach (var prop in properties) @@ -120,7 +120,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F } history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Deleted; - history.Changed = JsonSerializer.Serialize(json); + history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); break; case EntityState.Detached: case EntityState.Unchanged: @@ -194,7 +194,7 @@ internal static TAutoHistory AddedHistory( } history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Added; - history.Changed = JsonSerializer.Serialize(json); + history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); return history; } diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs index 05ea68f..3643663 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Arch team. All rights reserved. using System; +using System.Text.Json; using Microsoft.EntityFrameworkCore.Internal; namespace Microsoft.EntityFrameworkCore @@ -17,8 +18,9 @@ public static class ModelBuilderExtensions /// /// The to enable auto history feature. /// The maximum length of the 'Changed' column. null will use default setting 2048. + /// The json setting for the 'Changed' column /// The had enabled auto history feature. - public static ModelBuilder EnableAutoHistory(this ModelBuilder modelBuilder, int? changedMaxLength = null) + public static ModelBuilder EnableAutoHistory(this ModelBuilder modelBuilder, int? changedMaxLength = null, JsonSerializerOptions JsonSerializerOptions = null) { return ModelBuilderExtensions.EnableAutoHistory(modelBuilder, o => { From 3063cd126523458d2954ac2b731930ae6f765a64 Mon Sep 17 00:00:00 2001 From: Felix Hoi Date: Thu, 28 Oct 2021 15:03:43 +0800 Subject: [PATCH 12/23] fix JsonSerializerOptions not effective --- .../Extensions/ModelBuilderExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs index 3643663..4dd087e 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/ModelBuilderExtensions.cs @@ -26,6 +26,7 @@ public static ModelBuilder EnableAutoHistory(this ModelBuilder modelBuilder, int { o.ChangedMaxLength = changedMaxLength; o.LimitChangedLength = false; + o.JsonSerializerOptions = JsonSerializerOptions; }); } From 245b6987fa4d1f0ac3beb411bd0d040e956d5ff4 Mon Sep 17 00:00:00 2001 From: Felix Hoi Date: Thu, 28 Oct 2021 17:05:25 +0800 Subject: [PATCH 13/23] fix Does not record on DELETE issue #63 --- .../Extensions/DbContextExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index ee395a2..35ae16d 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -52,7 +52,7 @@ internal static TAutoHistory AutoHistory(this EntityEntry entry, F var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); //Bug: If remaining properties to check are not modified, AutoHistory still returns an object with empty changes. - if (properties.Any(p => p.IsModified)) + if (properties.Any(p => p.IsModified) || entry.State == EntityState.Deleted) { var history = createHistoryFactory(); history.TableName = entry.Metadata.GetTableName(); From 4eb6880851c0d7d62960e77d3a37660d130cd589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Pot=C3=AErnac?= Date: Sat, 27 Nov 2021 16:12:00 +0200 Subject: [PATCH 14/23] Add net6 support --- .../AspNetCore5.0.MVC.EF.Blogs.csproj | 5 +++-- .../Microsoft.EntityFrameworkCore.AutoHistory.csproj | 6 +++--- .../Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj index bcdfa59..ff7e2bc 100644 --- a/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj +++ b/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj @@ -1,12 +1,13 @@  - netcoreapp5.0 + net6.0 + - + diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj index 53b3b14..ae7ca3a 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj @@ -3,7 +3,7 @@ A plugin for Microsoft.EntityFrameworkCore to support automatically recording data changes history. 5.0.7 rigofunc;rigofunc@outlook.com - net5.0 + net6.0 $(NoWarn);CS1591 true true @@ -16,6 +16,6 @@ https://github.com/arch/AutoHistory.git - + - \ No newline at end of file + diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj index c13ecad..6e93f59 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/Microsoft.EntityFrameworkCore.AutoHistory.Test.csproj @@ -1,6 +1,6 @@  - netcoreapp5.0 + net6.0 $(NoWarn);CS1591 true Microsoft.EntityFrameworkCore.AutoHistory.Test @@ -8,8 +8,8 @@ true - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -22,4 +22,4 @@ - \ No newline at end of file + From bd7c2d8bc94d0ab42426831154bdba6e69665f7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Pot=C3=AErnac?= Date: Sat, 27 Nov 2021 16:12:41 +0200 Subject: [PATCH 15/23] Add deleted test --- .../AutoHistoryTest.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs index c7e6d86..6d9d763 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs @@ -57,5 +57,33 @@ public void Entity_Update_AutoHistory_Test() Assert.Equal(1, count); } } + + + [Fact] + public void Entity_Delete_AutoHistory_Test() + { + using var db = new BloggingContext(); + var blog = new Blog + { + Url = "http://blogs.msdn.com/adonet", + Posts = new List { + new Post { + Title = "xUnit", + Content = "Delete Post from xUnit test." + } + }, + PrivateURL = "http://www.secret.com" + }; + db.Attach(blog); + db.SaveChanges(); + + + db.Remove(blog); + db.EnsureAutoHistory(); + var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Deleted); + + // blog and post are deleted + Assert.Equal(2, count); + } } } From 9f34673a602b7303a92986444baee158fad8cf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Pot=C3=AErnac?= Date: Sat, 27 Nov 2021 16:14:48 +0200 Subject: [PATCH 16/23] Autohistory version to 6 --- .../Microsoft.EntityFrameworkCore.AutoHistory.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj index ae7ca3a..60e940d 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj @@ -1,7 +1,7 @@  A plugin for Microsoft.EntityFrameworkCore to support automatically recording data changes history. - 5.0.7 + 6.0.0 rigofunc;rigofunc@outlook.com net6.0 $(NoWarn);CS1591 From a7f929d54f17d8cecf8ad5842398846c2a327b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Pot=C3=AErnac?= Date: Sat, 27 Nov 2021 16:15:31 +0200 Subject: [PATCH 17/23] Rename sample from 5 to nothing we can avoid folder rename on future upgrades --- .../AspNetCore.MVC.EF.Blogs.csproj} | 0 .../Controllers/BlogsController.cs | 0 .../Migrations/20181226223513_Initial.Designer.cs | 0 .../Migrations/20181226223513_Initial.cs | 0 ...210705113831_blog_privateURLProperty.Designer.cs | 0 .../20210705113831_blog_privateURLProperty.cs | 0 .../Migrations/BloggingContextModelSnapshot.cs | 0 .../Models/ContextFactory.cs | 0 .../Models/ErrorViewModel.cs | 0 .../Models/Model.cs | 0 .../Program.cs | 0 .../Properties/launchSettings.json | 0 .../Startup.cs | 0 .../Views/Blogs/Create.cshtml | 0 .../Views/Blogs/Delete.cshtml | 0 .../Views/Blogs/Details.cshtml | 0 .../Views/Blogs/Edit.cshtml | 0 .../Views/Blogs/Index.cshtml | 0 .../Views/Shared/Error.cshtml | 0 .../Views/Shared/_CookieConsentPartial.cshtml | 0 .../Views/Shared/_Layout.cshtml | 0 .../Views/Shared/_ValidationScriptsPartial.cshtml | 0 .../Views/_ViewImports.cshtml | 0 .../Views/_ViewStart.cshtml | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../wwwroot/css/site.css | 0 .../wwwroot/favicon.ico | Bin .../wwwroot/js/site.js | 0 .../wwwroot/lib/bootstrap/LICENSE | 0 .../lib/bootstrap/dist/css/bootstrap-grid.css | 0 .../lib/bootstrap/dist/css/bootstrap-grid.css.map | 0 .../lib/bootstrap/dist/css/bootstrap-grid.min.css | 0 .../bootstrap/dist/css/bootstrap-grid.min.css.map | 0 .../lib/bootstrap/dist/css/bootstrap-reboot.css | 0 .../lib/bootstrap/dist/css/bootstrap-reboot.css.map | 0 .../lib/bootstrap/dist/css/bootstrap-reboot.min.css | 0 .../bootstrap/dist/css/bootstrap-reboot.min.css.map | 0 .../wwwroot/lib/bootstrap/dist/css/bootstrap.css | 0 .../lib/bootstrap/dist/css/bootstrap.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.min.css | 0 .../lib/bootstrap/dist/css/bootstrap.min.css.map | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.js | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.min.js | 0 .../bootstrap/dist/js/bootstrap.bundle.min.js.map | 0 .../wwwroot/lib/bootstrap/dist/js/bootstrap.js | 0 .../wwwroot/lib/bootstrap/dist/js/bootstrap.js.map | 0 .../wwwroot/lib/bootstrap/dist/js/bootstrap.min.js | 0 .../lib/bootstrap/dist/js/bootstrap.min.js.map | 0 .../lib/jquery-validation-unobtrusive/LICENSE.txt | 0 .../jquery.validate.unobtrusive.js | 0 .../jquery.validate.unobtrusive.min.js | 0 .../wwwroot/lib/jquery-validation/LICENSE.md | 0 .../jquery-validation/dist/additional-methods.js | 0 .../dist/additional-methods.min.js | 0 .../lib/jquery-validation/dist/jquery.validate.js | 0 .../jquery-validation/dist/jquery.validate.min.js | 0 .../wwwroot/lib/jquery/LICENSE.txt | 0 .../wwwroot/lib/jquery/dist/jquery.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.map | 0 62 files changed, 0 insertions(+), 0 deletions(-) rename samples/{AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj => AspNetCore.MVC.EF.Blogs/AspNetCore.MVC.EF.Blogs.csproj} (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Controllers/BlogsController.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Migrations/20181226223513_Initial.Designer.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Migrations/20181226223513_Initial.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Migrations/20210705113831_blog_privateURLProperty.Designer.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Migrations/20210705113831_blog_privateURLProperty.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Migrations/BloggingContextModelSnapshot.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Models/ContextFactory.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Models/ErrorViewModel.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Models/Model.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Program.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Properties/launchSettings.json (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Startup.cs (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Blogs/Create.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Blogs/Delete.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Blogs/Details.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Blogs/Edit.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Blogs/Index.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Shared/Error.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Shared/_CookieConsentPartial.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Shared/_Layout.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/Shared/_ValidationScriptsPartial.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/_ViewImports.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/Views/_ViewStart.cshtml (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/appsettings.Development.json (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/appsettings.json (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/css/site.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/favicon.ico (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/js/site.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/LICENSE (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/LICENSE.md (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/additional-methods.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/additional-methods.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/jquery.validate.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery/LICENSE.txt (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.min.js (100%) rename samples/{AspNetCore5.0.MVC.EF.Blogs => AspNetCore.MVC.EF.Blogs}/wwwroot/lib/jquery/dist/jquery.min.map (100%) diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj b/samples/AspNetCore.MVC.EF.Blogs/AspNetCore.MVC.EF.Blogs.csproj similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/AspNetCore5.0.MVC.EF.Blogs.csproj rename to samples/AspNetCore.MVC.EF.Blogs/AspNetCore.MVC.EF.Blogs.csproj diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs b/samples/AspNetCore.MVC.EF.Blogs/Controllers/BlogsController.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Controllers/BlogsController.cs rename to samples/AspNetCore.MVC.EF.Blogs/Controllers/BlogsController.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs b/samples/AspNetCore.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs rename to samples/AspNetCore.MVC.EF.Blogs/Migrations/20181226223513_Initial.Designer.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs b/samples/AspNetCore.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs rename to samples/AspNetCore.MVC.EF.Blogs/Migrations/20181226223513_Initial.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs b/samples/AspNetCore.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs rename to samples/AspNetCore.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.Designer.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs b/samples/AspNetCore.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs rename to samples/AspNetCore.MVC.EF.Blogs/Migrations/20210705113831_blog_privateURLProperty.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs b/samples/AspNetCore.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs rename to samples/AspNetCore.MVC.EF.Blogs/Migrations/BloggingContextModelSnapshot.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs b/samples/AspNetCore.MVC.EF.Blogs/Models/ContextFactory.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Models/ContextFactory.cs rename to samples/AspNetCore.MVC.EF.Blogs/Models/ContextFactory.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/ErrorViewModel.cs b/samples/AspNetCore.MVC.EF.Blogs/Models/ErrorViewModel.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Models/ErrorViewModel.cs rename to samples/AspNetCore.MVC.EF.Blogs/Models/ErrorViewModel.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs b/samples/AspNetCore.MVC.EF.Blogs/Models/Model.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Models/Model.cs rename to samples/AspNetCore.MVC.EF.Blogs/Models/Model.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Program.cs b/samples/AspNetCore.MVC.EF.Blogs/Program.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Program.cs rename to samples/AspNetCore.MVC.EF.Blogs/Program.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Properties/launchSettings.json b/samples/AspNetCore.MVC.EF.Blogs/Properties/launchSettings.json similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Properties/launchSettings.json rename to samples/AspNetCore.MVC.EF.Blogs/Properties/launchSettings.json diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Startup.cs b/samples/AspNetCore.MVC.EF.Blogs/Startup.cs similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Startup.cs rename to samples/AspNetCore.MVC.EF.Blogs/Startup.cs diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Create.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Create.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Create.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Delete.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Delete.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Delete.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Details.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Details.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Details.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Edit.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Edit.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Edit.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Index.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Blogs/Index.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Blogs/Index.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/Error.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Shared/Error.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/Error.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Shared/Error.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_CookieConsentPartial.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_Layout.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_Layout.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_Layout.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_Layout.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/Shared/_ValidationScriptsPartial.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewImports.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/_ViewImports.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewImports.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/_ViewImports.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewStart.cshtml b/samples/AspNetCore.MVC.EF.Blogs/Views/_ViewStart.cshtml similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/Views/_ViewStart.cshtml rename to samples/AspNetCore.MVC.EF.Blogs/Views/_ViewStart.cshtml diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.Development.json b/samples/AspNetCore.MVC.EF.Blogs/appsettings.Development.json similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.Development.json rename to samples/AspNetCore.MVC.EF.Blogs/appsettings.Development.json diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.json b/samples/AspNetCore.MVC.EF.Blogs/appsettings.json similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/appsettings.json rename to samples/AspNetCore.MVC.EF.Blogs/appsettings.json diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/css/site.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/css/site.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/css/site.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/css/site.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/favicon.ico b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/favicon.ico similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/favicon.ico rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/favicon.ico diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/js/site.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/js/site.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/js/site.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/js/site.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/LICENSE diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/LICENSE.md diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/additional-methods.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery-validation/dist/jquery.validate.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/LICENSE.txt diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.js diff --git a/samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map b/samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map similarity index 100% rename from samples/AspNetCore5.0.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map rename to samples/AspNetCore.MVC.EF.Blogs/wwwroot/lib/jquery/dist/jquery.min.map From b1a685e3ef08e0d4203e056e55e3eec5433442b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Pot=C3=AErnac?= Date: Sat, 27 Nov 2021 16:16:53 +0200 Subject: [PATCH 18/23] useless empty space --- .../AutoHistoryTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs index 6d9d763..33c5746 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryTest.cs @@ -77,7 +77,6 @@ public void Entity_Delete_AutoHistory_Test() db.Attach(blog); db.SaveChanges(); - db.Remove(blog); db.EnsureAutoHistory(); var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Deleted); From 365a7f88ab4a512f60faa5bed0036ae8497f41ae Mon Sep 17 00:00:00 2001 From: ThumNet Date: Fri, 1 Apr 2022 10:14:27 +0200 Subject: [PATCH 19/23] Add support to exclude entire entity from AutoHistory --- .../Extensions/DbContextExtensions.cs | 9 ++++++++- .../AutoHistoryExcludePropertyTest.cs | 20 +++++++++++++++++++ .../BloggingContext.cs | 11 +++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index 35ae16d..f1155e9 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -28,7 +28,9 @@ public static void EnsureAutoHistory(this DbContext context, Func< { // Must ToArray() here for excluding the AutoHistory model. // Currently, only support Modified and Deleted entity. - var entries = context.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified || e.State == EntityState.Deleted).ToArray(); + var entries = context.ChangeTracker.Entries() + .Where(e => e.State == EntityState.Modified || e.State == EntityState.Deleted) + .ToArray(); foreach (var entry in entries) { var autoHistory = entry.AutoHistory(createHistoryFactory); @@ -42,6 +44,11 @@ public static void EnsureAutoHistory(this DbContext context, Func< internal static TAutoHistory AutoHistory(this EntityEntry entry, Func createHistoryFactory) where TAutoHistory : AutoHistory { + if (entry.Metadata.ClrType.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Any()) + { + return null; + } + // Get not excluded mapped properties for the entity type. // (include shadow properties, not include navigations & references) diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs index 4009cfd..162cda6 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs @@ -65,5 +65,25 @@ public void Entity_Update_AutoHistory_Exclude_Changed_Test() Assert.Equal(1, count); } } + + [Fact] + public void Excluded_Entity_Update_AutoHistory_OnlyModified_Changed_Test() + { + using (var db = new BloggingContext()) + { + var notTracked = new NotTracked { Title = "don't track me" }; + + db.Attach(notTracked); + db.SaveChanges(); + + notTracked.Title = "still not tracked"; + db.EnsureAutoHistory(); + + var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Added); + + //No changes are made (excluded is the only property modified) + Assert.Equal(0, count); + } + } } } \ No newline at end of file diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs index a090ef2..3f32d37 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/BloggingContext.cs @@ -8,6 +8,8 @@ public class BloggingContext : DbContext { public DbSet Blogs { get; set; } public DbSet Posts { get; set; } + public DbSet NotTracked { get; set; } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -45,7 +47,7 @@ public class Blog { public int BlogId { get; set; } public string Url { get; set; } - + [ExcludeFromHistory] public string PrivateURL { get; set; } @@ -61,4 +63,11 @@ public class Post public int BlogId { get; set; } public Blog Blog { get; set; } } + + [ExcludeFromHistory] + public class NotTracked + { + public int NotTrackedId { get; set; } + public string Title { get; set; } + } } From 5e46e8da109abc34f5db3c7fec895f11b51e962e Mon Sep 17 00:00:00 2001 From: ThumNet Date: Fri, 1 Apr 2022 15:59:06 +0200 Subject: [PATCH 20/23] Refactor (extract into separate methods) --- .../Extensions/DbContextExtensions.cs | 216 ++++++++++-------- .../AutoHistoryExcludePropertyTest.cs | 2 +- 2 files changed, 118 insertions(+), 100 deletions(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index f1155e9..04a9e22 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -44,105 +44,54 @@ public static void EnsureAutoHistory(this DbContext context, Func< internal static TAutoHistory AutoHistory(this EntityEntry entry, Func createHistoryFactory) where TAutoHistory : AutoHistory { - if (entry.Metadata.ClrType.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Any()) + if (IsEntityExcluded(entry)) { return null; } - // Get not excluded mapped properties for the entity type. - // (include shadow properties, not include navigations & references) - - var excludedProperties = entry.Metadata.ClrType.GetProperties() - .Where(p => p.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Count() > 0) - .Select(p => p.Name); - - var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); - //Bug: If remaining properties to check are not modified, AutoHistory still returns an object with empty changes. - - if (properties.Any(p => p.IsModified) || entry.State == EntityState.Deleted) + var properties = GetPropertiesWithoutExcluded(entry); + if (!(properties.Any(p => p.IsModified) || entry.State == EntityState.Deleted)) { - var history = createHistoryFactory(); - history.TableName = entry.Metadata.GetTableName(); + return null; + } - dynamic json = new System.Dynamic.ExpandoObject(); - switch (entry.State) - { - case EntityState.Added: - foreach (var prop in properties) - { - if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey()) - { - continue; - } - ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue; - } + var history = createHistoryFactory(); + history.TableName = entry.Metadata.GetTableName(); + switch (entry.State) + { + case EntityState.Added: + WriteHistoryAddedState(history, properties); + break; + case EntityState.Modified: + WriteHistoryModifiedState(history, entry, properties); + break; + case EntityState.Deleted: + WriteHistoryDeletedState(history, entry, properties); + break; + case EntityState.Detached: + case EntityState.Unchanged: + default: + throw new NotSupportedException("AutoHistory only support Deleted and Modified entity."); + } - // REVIEW: what's the best way to set the RowId? - history.RowId = "0"; - history.Kind = EntityState.Added; - history.Changed = JsonSerializer.Serialize(json); - break; - case EntityState.Modified: - dynamic bef = new System.Dynamic.ExpandoObject(); - dynamic aft = new System.Dynamic.ExpandoObject(); - - PropertyValues databaseValues = null; - foreach (var prop in properties) - { - if (prop.IsModified) - { - if (prop.OriginalValue != null) - { - if (!prop.OriginalValue.Equals(prop.CurrentValue)) - { - ((IDictionary)bef)[prop.Metadata.Name] = prop.OriginalValue; - } - else - { - databaseValues ??= entry.GetDatabaseValues(); - var originalValue = databaseValues.GetValue(prop.Metadata.Name); - ((IDictionary)bef)[prop.Metadata.Name] = originalValue; - } - } - else - { - ((IDictionary)bef)[prop.Metadata.Name] = null; - } - - ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue; - } - } + return history; + } - ((IDictionary)json)["before"] = bef; - ((IDictionary)json)["after"] = aft; + private static bool IsEntityExcluded(EntityEntry entry) => + entry.Metadata.ClrType.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Any(); - history.RowId = entry.PrimaryKey(); - history.Kind = EntityState.Modified; - history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); - break; - case EntityState.Deleted: - foreach (var prop in properties) - { - ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue; - } - history.RowId = entry.PrimaryKey(); - history.Kind = EntityState.Deleted; - history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); - break; - case EntityState.Detached: - case EntityState.Unchanged: - default: - throw new NotSupportedException("AutoHistory only support Deleted and Modified entity."); - } + private static IEnumerable GetPropertiesWithoutExcluded(EntityEntry entry) + { + // Get the mapped properties for the entity type. + // (include shadow properties, not include navigations & references) + var excludedProperties = entry.Metadata.ClrType.GetProperties() + .Where(p => p.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Count() > 0) + .Select(p => p.Name); - return history; - } - else - { - return null; - } + var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); + return properties; } - + /// /// Ensures the history for added entries /// @@ -179,26 +128,22 @@ internal static TAutoHistory AddedHistory( Func createHistoryFactory) where TAutoHistory : AutoHistory { - var history = createHistoryFactory(); - history.TableName = entry.Metadata - .GetTableName(); - - // Get the mapped properties for the entity type. - // (include shadow properties, not include navigations & references) - var excludedProperties = entry.Metadata.ClrType.GetProperties() - .Where(p => p.GetCustomAttributes(typeof(ExcludeFromHistoryAttribute), true).Count() > 0) - .Select(p => p.Name); + if (!IsEntityExcluded(entry)) + { + return null; + } - var properties = entry.Properties.Where(f => !excludedProperties.Contains(f.Metadata.Name)); + var properties = GetPropertiesWithoutExcluded(entry); dynamic json = new System.Dynamic.ExpandoObject(); - foreach (var prop in properties) { ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue != null ? prop.OriginalValue : null; } + var history = createHistoryFactory(); + history.TableName = entry.Metadata.GetTableName(); history.RowId = entry.PrimaryKey(); history.Kind = EntityState.Added; history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); @@ -221,5 +166,78 @@ private static string PrimaryKey(this EntityEntry entry) return string.Join(",", values); } + + private static void WriteHistoryAddedState(AutoHistory history, IEnumerable properties) + { + dynamic json = new System.Dynamic.ExpandoObject(); + + foreach (var prop in properties) + { + if (prop.Metadata.IsKey() || prop.Metadata.IsForeignKey()) + { + continue; + } + ((IDictionary)json)[prop.Metadata.Name] = prop.CurrentValue; + } + + // REVIEW: what's the best way to set the RowId? + history.RowId = "0"; + history.Kind = EntityState.Added; + history.Changed = JsonSerializer.Serialize(json); + } + + private static void WriteHistoryModifiedState(AutoHistory history, EntityEntry entry, IEnumerable properties) + { + dynamic json = new System.Dynamic.ExpandoObject(); + dynamic bef = new System.Dynamic.ExpandoObject(); + dynamic aft = new System.Dynamic.ExpandoObject(); + + PropertyValues databaseValues = null; + foreach (var prop in properties) + { + if (prop.IsModified) + { + if (prop.OriginalValue != null) + { + if (!prop.OriginalValue.Equals(prop.CurrentValue)) + { + ((IDictionary)bef)[prop.Metadata.Name] = prop.OriginalValue; + } + else + { + databaseValues ??= entry.GetDatabaseValues(); + var originalValue = databaseValues.GetValue(prop.Metadata.Name); + ((IDictionary)bef)[prop.Metadata.Name] = originalValue; + } + } + else + { + ((IDictionary)bef)[prop.Metadata.Name] = null; + } + + ((IDictionary)aft)[prop.Metadata.Name] = prop.CurrentValue; + } + } + + ((IDictionary)json)["before"] = bef; + ((IDictionary)json)["after"] = aft; + + history.RowId = entry.PrimaryKey(); + history.Kind = EntityState.Modified; + history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); + } + + private static void WriteHistoryDeletedState(AutoHistory history, EntityEntry entry, IEnumerable properties) + { + dynamic json = new System.Dynamic.ExpandoObject(); + + foreach (var prop in properties) + { + ((IDictionary)json)[prop.Metadata.Name] = prop.OriginalValue; + } + history.RowId = entry.PrimaryKey(); + history.Kind = EntityState.Deleted; + history.Changed = JsonSerializer.Serialize(json, AutoHistoryOptions.Instance.JsonSerializerOptions); + } } } diff --git a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs index 162cda6..c42a2db 100644 --- a/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs +++ b/test/Microsoft.EntityFrameworkCore.AutoHistory.Test/AutoHistoryExcludePropertyTest.cs @@ -81,7 +81,7 @@ public void Excluded_Entity_Update_AutoHistory_OnlyModified_Changed_Test() var count = db.ChangeTracker.Entries().Count(e => e.State == EntityState.Added); - //No changes are made (excluded is the only property modified) + //No changes are made (entire entity is excluded) Assert.Equal(0, count); } } From 05c792f6e20d9691291dc6f105cc0ffca7023a3c Mon Sep 17 00:00:00 2001 From: ThumNet Date: Sun, 3 Apr 2022 21:32:38 +0200 Subject: [PATCH 21/23] Fix AddedHistory returned null wrongly --- .../Extensions/DbContextExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs index 04a9e22..9f7b1ec 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Extensions/DbContextExtensions.cs @@ -128,7 +128,7 @@ internal static TAutoHistory AddedHistory( Func createHistoryFactory) where TAutoHistory : AutoHistory { - if (!IsEntityExcluded(entry)) + if (IsEntityExcluded(entry)) { return null; } From d9d062aa9d2536040b4ce0ae8b0b275afeb9c3c8 Mon Sep 17 00:00:00 2001 From: yingtingxu Date: Wed, 14 Dec 2022 16:07:23 +0800 Subject: [PATCH 22/23] docs: comment out the NuGet.config --- NuGet.config | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/NuGet.config b/NuGet.config index 135a50b..4e11f1b 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + From aa60f0215f05ce53eb384a6e3430555546b63146 Mon Sep 17 00:00:00 2001 From: yingtingxu Date: Tue, 4 Apr 2023 13:48:48 +0800 Subject: [PATCH 23/23] chore: update --- AutoHistory.sln | 1 - .../Microsoft.EntityFrameworkCore.AutoHistory.csproj | 2 ++ .../Microsoft.EntityFrameworkCore.AutoHistory/README.md | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename README.md => src/Microsoft.EntityFrameworkCore.AutoHistory/README.md (100%) diff --git a/AutoHistory.sln b/AutoHistory.sln index dec2726..ec1eaaf 100644 --- a/AutoHistory.sln +++ b/AutoHistory.sln @@ -15,7 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig NuGet.config = NuGet.config - README.md = README.md EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{1C12ACF7-CF58-460C-8EF3-2349D8E62AC1}" diff --git a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj index 60e940d..6c41a53 100644 --- a/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj +++ b/src/Microsoft.EntityFrameworkCore.AutoHistory/Microsoft.EntityFrameworkCore.AutoHistory.csproj @@ -6,6 +6,7 @@ net6.0 $(NoWarn);CS1591 true + README.md true Microsoft.EntityFrameworkCore.AutoHistory Microsoft.EntityFrameworkCore.AutoHistory @@ -17,5 +18,6 @@ + diff --git a/README.md b/src/Microsoft.EntityFrameworkCore.AutoHistory/README.md similarity index 100% rename from README.md rename to src/Microsoft.EntityFrameworkCore.AutoHistory/README.md