diff --git a/samples/EfCoreMigrationDemo/.gitattributes b/samples/EfCoreMigrationDemo/.gitattributes
new file mode 100644
index 0000000000..c941e52669
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/.gitattributes
@@ -0,0 +1 @@
+**/wwwroot/libs/** linguist-vendored
diff --git a/samples/EfCoreMigrationDemo/.gitignore b/samples/EfCoreMigrationDemo/.gitignore
new file mode 100644
index 0000000000..e9ccd519eb
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/.gitignore
@@ -0,0 +1,259 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# BookStore
+src/Acme.BookStore.Web/Logs/*
+src/Acme.BookStore.Web.Host/Logs/*
+src/Acme.BookStore.IdentityServer/Logs/*
+src/Acme.BookStore.HttpApi.Host/Logs/*
+src/Acme.BookStore.HttpApi.HostWithIds/Logs/*
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/Acme.BookStore.sln b/samples/EfCoreMigrationDemo/Acme.BookStore.sln
new file mode 100644
index 0000000000..5750b0dbef
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/Acme.BookStore.sln
@@ -0,0 +1,137 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29020.237
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain", "src\Acme.BookStore.Domain\Acme.BookStore.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application", "src\Acme.BookStore.Application\Acme.BookStore.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.EntityFrameworkCore", "src\Acme.BookStore.EntityFrameworkCore\Acme.BookStore.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Web", "src\Acme.BookStore.Web\Acme.BookStore.Web.csproj", "{068855E8-9240-4F1A-910B-CF825794513B}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{04DBDB01-70F4-4E06-B468-8F87850B22BE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application.Tests", "test\Acme.BookStore.Application.Tests\Acme.BookStore.Application.Tests.csproj", "{50B2631D-129C-47B3-A587-029CCD6099BC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Web.Tests", "test\Acme.BookStore.Web.Tests\Acme.BookStore.Web.Tests.csproj", "{5F1B28C6-8D0C-4155-92D0-252F7EA5F674}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.EntityFrameworkCore.DbMigrations", "src\Acme.BookStore.EntityFrameworkCore.DbMigrations\Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj", "{0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Shared", "src\Acme.BookStore.Domain.Shared\Acme.BookStore.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Application.Contracts", "src\Acme.BookStore.Application.Contracts\Acme.BookStore.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi", "src\Acme.BookStore.HttpApi\Acme.BookStore.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi.Client", "src\Acme.BookStore.HttpApi.Client\Acme.BookStore.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.EntityFrameworkCore.Tests", "test\Acme.BookStore.EntityFrameworkCore.Tests\Acme.BookStore.EntityFrameworkCore.Tests.csproj", "{1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.TestBase", "test\Acme.BookStore.TestBase\Acme.BookStore.TestBase.csproj", "{91853F21-9CD9-4132-BC29-A7D5D84FFFE7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.Domain.Tests", "test\Acme.BookStore.Domain.Tests\Acme.BookStore.Domain.Tests.csproj", "{E512F4D9-9375-480F-A2F6-A46509F9D824}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.HttpApi.Client.ConsoleTestApp", "test\Acme.BookStore.HttpApi.Client.ConsoleTestApp\Acme.BookStore.HttpApi.Client.ConsoleTestApp.csproj", "{EF480016-9127-4916-8735-D2466BDBC582}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Acme.BookStore.DbMigrator", "src\Acme.BookStore.DbMigrator\Acme.BookStore.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {068855E8-9240-4F1A-910B-CF825794513B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {068855E8-9240-4F1A-910B-CF825794513B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {068855E8-9240-4F1A-910B-CF825794513B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {068855E8-9240-4F1A-910B-CF825794513B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {50B2631D-129C-47B3-A587-029CCD6099BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {50B2631D-129C-47B3-A587-029CCD6099BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {50B2631D-129C-47B3-A587-029CCD6099BC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5F1B28C6-8D0C-4155-92D0-252F7EA5F674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5F1B28C6-8D0C-4155-92D0-252F7EA5F674}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5F1B28C6-8D0C-4155-92D0-252F7EA5F674}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5F1B28C6-8D0C-4155-92D0-252F7EA5F674}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81}.Release|Any CPU.Build.0 = Release|Any CPU
+ {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {91853F21-9CD9-4132-BC29-A7D5D84FFFE7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E512F4D9-9375-480F-A2F6-A46509F9D824}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E512F4D9-9375-480F-A2F6-A46509F9D824}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF480016-9127-4916-8735-D2466BDBC582}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF480016-9127-4916-8735-D2466BDBC582}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {068855E8-9240-4F1A-910B-CF825794513B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {50B2631D-129C-47B3-A587-029CCD6099BC} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {5F1B28C6-8D0C-4155-92D0-252F7EA5F674} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {0372FA84-C517-4EB3-9A9F-B9ACAC0CA5E0} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {1FE30EB9-74A9-47F5-A9F6-7B1FAB672D81} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {91853F21-9CD9-4132-BC29-A7D5D84FFFE7} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {E512F4D9-9375-480F-A2F6-A46509F9D824} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F}
+ EndGlobalSection
+EndGlobal
diff --git a/samples/EfCoreMigrationDemo/Acme.BookStore.sln.DotSettings b/samples/EfCoreMigrationDemo/Acme.BookStore.sln.DotSettings
new file mode 100644
index 0000000000..cb0b2c919f
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/Acme.BookStore.sln.DotSettings
@@ -0,0 +1,23 @@
+
+ True
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ Required
+ Required
+ Required
+ Required
+ False
+ True
+ False
+ False
+ True
+ False
+ False
+ SQL
+
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/common.props b/samples/EfCoreMigrationDemo/common.props
new file mode 100644
index 0000000000..7585f303ba
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/common.props
@@ -0,0 +1,7 @@
+
+
+ latest
+ 1.0.0
+ $(NoWarn);CS1591
+
+
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj
new file mode 100644
index 0000000000..78fbf262c3
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Acme.BookStore.Application.Contracts.csproj
@@ -0,0 +1,22 @@
+
+
+
+
+
+ netstandard2.0
+ Acme.BookStore
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs
new file mode 100644
index 0000000000..b085b223d4
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/BookStoreApplicationContractsModule.cs
@@ -0,0 +1,22 @@
+using Volo.Abp.Account;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Acme.BookStore
+{
+ [DependsOn(
+ typeof(BookStoreDomainSharedModule),
+ typeof(AbpAccountApplicationContractsModule),
+ typeof(AbpFeatureManagementApplicationContractsModule),
+ typeof(AbpIdentityApplicationContractsModule),
+ typeof(AbpPermissionManagementApplicationContractsModule),
+ typeof(AbpTenantManagementApplicationContractsModule)
+ )]
+ public class BookStoreApplicationContractsModule : AbpModule
+ {
+
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissionDefinitionProvider.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissionDefinitionProvider.cs
new file mode 100644
index 0000000000..e189ca3743
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissionDefinitionProvider.cs
@@ -0,0 +1,22 @@
+using Acme.BookStore.Localization;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Localization;
+
+namespace Acme.BookStore.Permissions
+{
+ public class BookStorePermissionDefinitionProvider : PermissionDefinitionProvider
+ {
+ public override void Define(IPermissionDefinitionContext context)
+ {
+ var myGroup = context.AddGroup(BookStorePermissions.GroupName);
+
+ //Define your own permissions here. Example:
+ //myGroup.AddPermission(BookStorePermissions.MyPermission1, L("Permission:MyPermission1"));
+ }
+
+ private static LocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissions.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissions.cs
new file mode 100644
index 0000000000..b05c4883bd
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Permissions/BookStorePermissions.cs
@@ -0,0 +1,10 @@
+namespace Acme.BookStore.Permissions
+{
+ public static class BookStorePermissions
+ {
+ public const string GroupName = "BookStore";
+
+ //Add your own permission names. Example:
+ //public const string MyPermission1 = GroupName + ".MyPermission1";
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/AppRoleDto.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/AppRoleDto.cs
new file mode 100644
index 0000000000..da610e517c
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/AppRoleDto.cs
@@ -0,0 +1,12 @@
+using System;
+using Volo.Abp.Application.Dtos;
+
+namespace Acme.BookStore.Roles
+{
+ public class AppRoleDto : EntityDto
+ {
+ public string Name { get; set; }
+
+ public string Title { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/IAppRoleAppService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/IAppRoleAppService.cs
new file mode 100644
index 0000000000..89d5d1fab3
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application.Contracts/Roles/IAppRoleAppService.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+
+namespace Acme.BookStore.Roles
+{
+ public interface IAppRoleAppService : IApplicationService
+ {
+ Task> GetListAsync();
+
+ Task UpdateTitleAsync(Guid id, string title);
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj
new file mode 100644
index 0000000000..01884a764b
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Acme.BookStore.Application.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+
+ netcoreapp3.1
+ Acme.BookStore
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreAppService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreAppService.cs
new file mode 100644
index 0000000000..06da155c39
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreAppService.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Acme.BookStore.Localization;
+using Volo.Abp.Application.Services;
+
+namespace Acme.BookStore
+{
+ /* Inherit your application services from this class.
+ */
+ public abstract class BookStoreAppService : ApplicationService
+ {
+ protected BookStoreAppService()
+ {
+ LocalizationResource = typeof(BookStoreResource);
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
new file mode 100644
index 0000000000..0706d83633
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationAutoMapperProfile.cs
@@ -0,0 +1,14 @@
+using AutoMapper;
+
+namespace Acme.BookStore
+{
+ public class BookStoreApplicationAutoMapperProfile : Profile
+ {
+ public BookStoreApplicationAutoMapperProfile()
+ {
+ /* You can configure your AutoMapper mapping configuration here.
+ * Alternatively, you can split your mapping configurations
+ * into multiple profile classes for a better organization. */
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationModule.cs
new file mode 100644
index 0000000000..35f248fde3
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/BookStoreApplicationModule.cs
@@ -0,0 +1,30 @@
+using Volo.Abp.Account;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Acme.BookStore
+{
+ [DependsOn(
+ typeof(BookStoreDomainModule),
+ typeof(AbpAccountApplicationModule),
+ typeof(BookStoreApplicationContractsModule),
+ typeof(AbpIdentityApplicationModule),
+ typeof(AbpPermissionManagementApplicationModule),
+ typeof(AbpTenantManagementApplicationModule),
+ typeof(AbpFeatureManagementApplicationModule)
+ )]
+ public class BookStoreApplicationModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.AddMaps();
+ });
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/AppRoleAppService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/AppRoleAppService.cs
new file mode 100644
index 0000000000..cdbe0e2d79
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/AppRoleAppService.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Volo.Abp.Application.Services;
+using Volo.Abp.Domain.Repositories;
+
+namespace Acme.BookStore.Roles
+{
+ public class AppRoleAppService : ApplicationService, IAppRoleAppService
+ {
+ private readonly IRepository _appRoleRepository;
+
+ public AppRoleAppService(IRepository appRoleRepository)
+ {
+ _appRoleRepository = appRoleRepository;
+ }
+
+ public async Task> GetListAsync()
+ {
+ var roles = await _appRoleRepository.GetListAsync();
+
+ return roles
+ .Select(r => new AppRoleDto
+ {
+ Id = r.Id,
+ Name = r.Name,
+ Title = r.Title
+ })
+ .ToList();
+ }
+
+ public async Task UpdateTitleAsync(Guid id, string title)
+ {
+ var role = await _appRoleRepository.GetAsync(id);
+
+ role.Title = title;
+
+ await _appRoleRepository.UpdateAsync(role);
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/IdentityRoleExtendingService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/IdentityRoleExtendingService.cs
new file mode 100644
index 0000000000..8b0f6aca69
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Application/Roles/IdentityRoleExtendingService.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Identity;
+
+namespace Acme.BookStore.Roles
+{
+ public class IdentityRoleExtendingService : ITransientDependency
+ {
+ private readonly IIdentityRoleRepository _identityRoleRepository;
+
+ public IdentityRoleExtendingService(IIdentityRoleRepository identityRoleRepository)
+ {
+ _identityRoleRepository = identityRoleRepository;
+ }
+
+
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj
new file mode 100644
index 0000000000..0ca05be4b6
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Acme.BookStore.DbMigrator.csproj
@@ -0,0 +1,34 @@
+
+
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
+
+
+
+
+
+ PreserveNewest
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs
new file mode 100644
index 0000000000..6938a9ae92
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/BookStoreDbMigratorModule.cs
@@ -0,0 +1,20 @@
+using Acme.BookStore.EntityFrameworkCore;
+using Volo.Abp.Autofac;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.Modularity;
+
+namespace Acme.BookStore.DbMigrator
+{
+ [DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(BookStoreEntityFrameworkCoreDbMigrationsModule),
+ typeof(BookStoreApplicationContractsModule)
+ )]
+ public class BookStoreDbMigratorModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options => options.IsJobExecutionEnabled = false);
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/DbMigratorHostedService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/DbMigratorHostedService.cs
new file mode 100644
index 0000000000..aef3d88bb5
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/DbMigratorHostedService.cs
@@ -0,0 +1,34 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Acme.BookStore.Data;
+using Serilog;
+using Volo.Abp;
+
+namespace Acme.BookStore.DbMigrator
+{
+ public class DbMigratorHostedService : IHostedService
+ {
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ using (var application = AbpApplicationFactory.Create(options =>
+ {
+ options.UseAutofac();
+ options.Services.AddLogging(c => c.AddSerilog());
+ }))
+ {
+ application.Initialize();
+
+ await application
+ .ServiceProvider
+ .GetRequiredService()
+ .MigrateAsync();
+
+ application.Shutdown();
+ }
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Program.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Program.cs
new file mode 100644
index 0000000000..179c18f4ca
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/Program.cs
@@ -0,0 +1,38 @@
+using System.IO;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Serilog;
+using Serilog.Events;
+
+namespace Acme.BookStore.DbMigrator
+{
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
+ .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning)
+#if DEBUG
+ .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Debug)
+#else
+ .MinimumLevel.Override("Acme.BookStore", LogEventLevel.Information)
+#endif
+ .Enrich.FromLogContext()
+ .WriteTo.File(Path.Combine(Directory.GetCurrentDirectory(), "Logs/logs.txt"))
+ .WriteTo.Console()
+ .CreateLogger();
+
+ await CreateHostBuilder(args).RunConsoleAsync();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureServices((hostContext, services) =>
+ {
+ services.AddHostedService();
+ });
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/appsettings.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/appsettings.json
new file mode 100644
index 0000000000..f6b326ced2
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.DbMigrator/appsettings.json
@@ -0,0 +1,18 @@
+{
+ "ConnectionStrings": {
+ "Default": "Server=localhost;Database=BookStore;Trusted_Connection=True;MultipleActiveResultSets=true"
+ },
+ "IdentityServer": {
+ "Clients": {
+ "BookStore_Web": {
+ "ClientId": "BookStore_Web",
+ "ClientSecret": "1q2w3e*",
+ "RootUrl": "https://localhost:44312"
+ },
+ "BookStore_App": {
+ "ClientId": "BookStore_App",
+ "ClientSecret": "1q2w3e*"
+ }
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj
new file mode 100644
index 0000000000..5f6c8b5fe5
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Acme.BookStore.Domain.Shared.csproj
@@ -0,0 +1,26 @@
+
+
+
+
+
+ netstandard2.0
+ Acme.BookStore
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs
new file mode 100644
index 0000000000..30f124fbed
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainErrorCodes.cs
@@ -0,0 +1,7 @@
+namespace Acme.BookStore
+{
+ public static class BookStoreDomainErrorCodes
+ {
+ /* You can add your business exception error codes here, as constants */
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs
new file mode 100644
index 0000000000..1d5c43b39c
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/BookStoreDomainSharedModule.cs
@@ -0,0 +1,45 @@
+using Acme.BookStore.Localization;
+using Volo.Abp.AuditLogging;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.IdentityServer;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+using Volo.Abp.Validation.Localization;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Acme.BookStore
+{
+ [DependsOn(
+ typeof(AbpAuditLoggingDomainSharedModule),
+ typeof(AbpBackgroundJobsDomainSharedModule),
+ typeof(AbpFeatureManagementDomainSharedModule),
+ typeof(AbpIdentityDomainSharedModule),
+ typeof(AbpIdentityServerDomainSharedModule),
+ typeof(AbpPermissionManagementDomainSharedModule),
+ typeof(AbpSettingManagementDomainSharedModule),
+ typeof(AbpTenantManagementDomainSharedModule)
+ )]
+ public class BookStoreDomainSharedModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded("Acme.BookStore");
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Add("en")
+ .AddBaseTypes(typeof(AbpValidationResource))
+ .AddVirtualJson("/Localization/BookStore");
+ });
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json
new file mode 100644
index 0000000000..619521939c
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/cs.json
@@ -0,0 +1,8 @@
+{
+ "culture": "cs",
+ "texts": {
+ "Menu:Home": "Úvod",
+ "Welcome": "Vítejte",
+ "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io."
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
new file mode 100644
index 0000000000..baa9fe753e
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/en.json
@@ -0,0 +1,8 @@
+{
+ "culture": "en",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Welcome",
+ "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io."
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json
new file mode 100644
index 0000000000..815bbcc83f
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pl.json
@@ -0,0 +1,8 @@
+{
+ "culture": "pl",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Witaj",
+ "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io."
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pt-BR.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pt-BR.json
new file mode 100644
index 0000000000..8c818a07af
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/pt-BR.json
@@ -0,0 +1,8 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "Menu:Home": "Principal",
+ "Welcome": "Seja bem-vindo!",
+ "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io."
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/tr.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/tr.json
new file mode 100644
index 0000000000..5bf83ee7a8
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/tr.json
@@ -0,0 +1,8 @@
+{
+ "culture": "tr",
+ "texts": {
+ "Menu:Home": "Ana sayfa",
+ "Welcome": "Hoşgeldiniz",
+ "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz."
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json
new file mode 100644
index 0000000000..c115a35726
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/vi.json
@@ -0,0 +1,8 @@
+{
+ "culture": "vi",
+ "texts": {
+ "Menu:Home": "Trang chủ",
+ "Welcome": "Chào mừng bạn",
+ "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io."
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json
new file mode 100644
index 0000000000..23790bde50
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hans.json
@@ -0,0 +1,8 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "Menu:Home": "首页",
+ "Welcome": "欢迎",
+ "LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 abp.io."
+ }
+ }
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hant.json b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hant.json
new file mode 100644
index 0000000000..31e0ab5a47
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStore/zh-Hant.json
@@ -0,0 +1,8 @@
+{
+ "culture": "zh-Hant",
+ "texts": {
+ "Menu:Home": "首頁",
+ "Welcome": "歡迎",
+ "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io."
+ }
+ }
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs
new file mode 100644
index 0000000000..cc4b935e58
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/Localization/BookStoreResource.cs
@@ -0,0 +1,10 @@
+using Volo.Abp.Localization;
+
+namespace Acme.BookStore.Localization
+{
+ [LocalizationResourceName("BookStore")]
+ public class BookStoreResource
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs
new file mode 100644
index 0000000000..9ece5cc53e
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs
@@ -0,0 +1,11 @@
+namespace Acme.BookStore.MultiTenancy
+{
+ public static class MultiTenancyConsts
+ {
+ /* Enable/disable multi-tenancy easily in a single point.
+ * If you will never need to multi-tenancy, you can remove
+ * related modules and code parts, including this file.
+ */
+ public const bool IsEnabled = true;
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj
new file mode 100644
index 0000000000..4f6d4e80f7
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Acme.BookStore.Domain.csproj
@@ -0,0 +1,27 @@
+
+
+
+
+
+ netcoreapp3.1
+ Acme.BookStore
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreConsts.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreConsts.cs
new file mode 100644
index 0000000000..96556e1b85
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreConsts.cs
@@ -0,0 +1,9 @@
+namespace Acme.BookStore
+{
+ public static class BookStoreConsts
+ {
+ public const string DbTablePrefix = "App";
+
+ public const string DbSchema = null;
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreDomainModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreDomainModule.cs
new file mode 100644
index 0000000000..2f3f2610a9
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/BookStoreDomainModule.cs
@@ -0,0 +1,38 @@
+using Acme.BookStore.MultiTenancy;
+using Volo.Abp.AuditLogging;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.IdentityServer;
+using Volo.Abp.Modularity;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.PermissionManagement.Identity;
+using Volo.Abp.PermissionManagement.IdentityServer;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Acme.BookStore
+{
+ [DependsOn(
+ typeof(BookStoreDomainSharedModule),
+ typeof(AbpAuditLoggingDomainModule),
+ typeof(AbpBackgroundJobsDomainModule),
+ typeof(AbpFeatureManagementDomainModule),
+ typeof(AbpIdentityDomainModule),
+ typeof(AbpPermissionManagementDomainIdentityModule),
+ typeof(AbpIdentityServerDomainModule),
+ typeof(AbpPermissionManagementDomainIdentityServerModule),
+ typeof(AbpSettingManagementDomainModule),
+ typeof(AbpTenantManagementDomainModule)
+ )]
+ public class BookStoreDomainModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.IsEnabled = MultiTenancyConsts.IsEnabled;
+ });
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs
new file mode 100644
index 0000000000..96d376467f
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/BookStoreDbMigrationService.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.TenantManagement;
+
+namespace Acme.BookStore.Data
+{
+ public class BookStoreDbMigrationService : ITransientDependency
+ {
+ public ILogger Logger { get; set; }
+
+ private readonly IDataSeeder _dataSeeder;
+ private readonly IBookStoreDbSchemaMigrator _dbSchemaMigrator;
+ private readonly ITenantRepository _tenantRepository;
+ private readonly ICurrentTenant _currentTenant;
+
+ public BookStoreDbMigrationService(
+ IDataSeeder dataSeeder,
+ IBookStoreDbSchemaMigrator dbSchemaMigrator,
+ ITenantRepository tenantRepository,
+ ICurrentTenant currentTenant)
+ {
+ _dataSeeder = dataSeeder;
+ _dbSchemaMigrator = dbSchemaMigrator;
+ _tenantRepository = tenantRepository;
+ _currentTenant = currentTenant;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async Task MigrateAsync()
+ {
+ Logger.LogInformation("Started database migrations...");
+
+ await MigrateHostDatabaseAsync();
+
+ var i = 0;
+ var tenants = await _tenantRepository.GetListAsync();
+ foreach (var tenant in tenants)
+ {
+ i++;
+
+ using (_currentTenant.Change(tenant.Id))
+ {
+ Logger.LogInformation($"Migrating {tenant.Name} database schema... ({i} of {tenants.Count})");
+ await MigrateTenantDatabasesAsync(tenant);
+ Logger.LogInformation($"Successfully completed {tenant.Name} database migrations.");
+ }
+ }
+
+ Logger.LogInformation("Successfully completed database migrations.");
+ }
+
+ private async Task MigrateHostDatabaseAsync()
+ {
+ Logger.LogInformation("Migrating host database schema...");
+ await _dbSchemaMigrator.MigrateAsync();
+
+ Logger.LogInformation("Executing host database seed...");
+ await _dataSeeder.SeedAsync();
+
+ Logger.LogInformation("Successfully completed host database migrations.");
+ }
+
+ private async Task MigrateTenantDatabasesAsync(Tenant tenant)
+ {
+ Logger.LogInformation($"Migrating schema for {tenant.Name} database...");
+ await _dbSchemaMigrator.MigrateAsync();
+
+ Logger.LogInformation($"Executing {tenant.Name} tenant database seed...");
+ await _dataSeeder.SeedAsync(tenant.Id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs
new file mode 100644
index 0000000000..5c94a6918e
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/IBookStoreDbSchemaMigrator.cs
@@ -0,0 +1,9 @@
+using System.Threading.Tasks;
+
+namespace Acme.BookStore.Data
+{
+ public interface IBookStoreDbSchemaMigrator
+ {
+ Task MigrateAsync();
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs
new file mode 100644
index 0000000000..f6ed8fc8de
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Data/NullBookStoreDbSchemaMigrator.cs
@@ -0,0 +1,16 @@
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace Acme.BookStore.Data
+{
+ /* This is used if database provider does't define
+ * IBookStoreDbSchemaMigrator implementation.
+ */
+ public class NullBookStoreDbSchemaMigrator : IBookStoreDbSchemaMigrator, ITransientDependency
+ {
+ public Task MigrateAsync()
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs
new file mode 100644
index 0000000000..03d336f18e
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/IdentityServer/IdentityServerDataSeedContributor.cs
@@ -0,0 +1,223 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using IdentityServer4.Models;
+using Microsoft.Extensions.Configuration;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.IdentityServer.ApiResources;
+using Volo.Abp.IdentityServer.Clients;
+using Volo.Abp.IdentityServer.IdentityResources;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.Uow;
+using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource;
+using Client = Volo.Abp.IdentityServer.Clients.Client;
+
+namespace Acme.BookStore.IdentityServer
+{
+ public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency
+ {
+ private readonly IApiResourceRepository _apiResourceRepository;
+ private readonly IClientRepository _clientRepository;
+ private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
+ private readonly IGuidGenerator _guidGenerator;
+ private readonly IPermissionDataSeeder _permissionDataSeeder;
+ private readonly IConfiguration _configuration;
+
+ public IdentityServerDataSeedContributor(
+ IClientRepository clientRepository,
+ IApiResourceRepository apiResourceRepository,
+ IIdentityResourceDataSeeder identityResourceDataSeeder,
+ IGuidGenerator guidGenerator,
+ IPermissionDataSeeder permissionDataSeeder,
+ IConfiguration configuration)
+ {
+ _clientRepository = clientRepository;
+ _apiResourceRepository = apiResourceRepository;
+ _identityResourceDataSeeder = identityResourceDataSeeder;
+ _guidGenerator = guidGenerator;
+ _permissionDataSeeder = permissionDataSeeder;
+ _configuration = configuration;
+ }
+
+ [UnitOfWork]
+ public virtual async Task SeedAsync(DataSeedContext context)
+ {
+ await _identityResourceDataSeeder.CreateStandardResourcesAsync();
+ await CreateApiResourcesAsync();
+ await CreateClientsAsync();
+ }
+
+ private async Task CreateApiResourcesAsync()
+ {
+ var commonApiUserClaims = new[]
+ {
+ "email",
+ "email_verified",
+ "name",
+ "phone_number",
+ "phone_number_verified",
+ "role"
+ };
+
+ await CreateApiResourceAsync("BookStore", commonApiUserClaims);
+ }
+
+ private async Task CreateApiResourceAsync(string name, IEnumerable claims)
+ {
+ var apiResource = await _apiResourceRepository.FindByNameAsync(name);
+ if (apiResource == null)
+ {
+ apiResource = await _apiResourceRepository.InsertAsync(
+ new ApiResource(
+ _guidGenerator.Create(),
+ name,
+ name + " API"
+ ),
+ autoSave: true
+ );
+ }
+
+ foreach (var claim in claims)
+ {
+ if (apiResource.FindClaim(claim) == null)
+ {
+ apiResource.AddUserClaim(claim);
+ }
+ }
+
+ return await _apiResourceRepository.UpdateAsync(apiResource);
+ }
+
+ private async Task CreateClientsAsync()
+ {
+ var commonScopes = new[]
+ {
+ "email",
+ "openid",
+ "profile",
+ "role",
+ "phone",
+ "address",
+ "BookStore"
+ };
+
+ var configurationSection = _configuration.GetSection("IdentityServer:Clients");
+
+ //Web Client
+ var webClientId = configurationSection["BookStore_Web:ClientId"];
+ if (!webClientId.IsNullOrWhiteSpace())
+ {
+ var webClientRootUrl = configurationSection["BookStore_Web:RootUrl"].EnsureEndsWith('/');
+
+ /* BookStore_Web client is only needed if you created a tiered
+ * solution. Otherwise, you can delete this client. */
+
+ await CreateClientAsync(
+ webClientId,
+ commonScopes,
+ new[] { "hybrid" },
+ (configurationSection["BookStore_Web:ClientSecret"] ?? "1q2w3e*").Sha256(),
+ redirectUri: $"{webClientRootUrl}signin-oidc",
+ postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc"
+ );
+ }
+
+ //Console Test Client
+ var consoleClientId = configurationSection["BookStore_App:ClientId"];
+ if (!consoleClientId.IsNullOrWhiteSpace())
+ {
+ await CreateClientAsync(
+ consoleClientId,
+ commonScopes,
+ new[] { "password", "client_credentials" },
+ (configurationSection["BookStore_App:ClientSecret"] ?? "1q2w3e*").Sha256()
+ );
+ }
+ }
+
+ private async Task CreateClientAsync(
+ string name,
+ IEnumerable scopes,
+ IEnumerable grantTypes,
+ string secret,
+ string redirectUri = null,
+ string postLogoutRedirectUri = null,
+ IEnumerable permissions = null)
+ {
+ var client = await _clientRepository.FindByCliendIdAsync(name);
+ if (client == null)
+ {
+ client = await _clientRepository.InsertAsync(
+ new Client(
+ _guidGenerator.Create(),
+ name
+ )
+ {
+ ClientName = name,
+ ProtocolType = "oidc",
+ Description = name,
+ AlwaysIncludeUserClaimsInIdToken = true,
+ AllowOfflineAccess = true,
+ AbsoluteRefreshTokenLifetime = 31536000, //365 days
+ AccessTokenLifetime = 31536000, //365 days
+ AuthorizationCodeLifetime = 300,
+ IdentityTokenLifetime = 300,
+ RequireConsent = false
+ },
+ autoSave: true
+ );
+ }
+
+ foreach (var scope in scopes)
+ {
+ if (client.FindScope(scope) == null)
+ {
+ client.AddScope(scope);
+ }
+ }
+
+ foreach (var grantType in grantTypes)
+ {
+ if (client.FindGrantType(grantType) == null)
+ {
+ client.AddGrantType(grantType);
+ }
+ }
+
+ if (client.FindSecret(secret) == null)
+ {
+ client.AddSecret(secret);
+ }
+
+ if (redirectUri != null)
+ {
+ if (client.FindRedirectUri(redirectUri) == null)
+ {
+ client.AddRedirectUri(redirectUri);
+ }
+ }
+
+ if (postLogoutRedirectUri != null)
+ {
+ if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null)
+ {
+ client.AddPostLogoutRedirectUri(postLogoutRedirectUri);
+ }
+ }
+
+ if (permissions != null)
+ {
+ await _permissionDataSeeder.SeedAsync(
+ ClientPermissionValueProvider.ProviderName,
+ name,
+ permissions
+ );
+ }
+
+ return await _clientRepository.UpdateAsync(client);
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Roles/AppRole.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Roles/AppRole.cs
new file mode 100644
index 0000000000..cb77f4721b
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Roles/AppRole.cs
@@ -0,0 +1,23 @@
+using System;
+using Volo.Abp.Domain.Entities;
+using Volo.Abp.MultiTenancy;
+
+namespace Acme.BookStore.Roles
+{
+ public class AppRole : AggregateRoot, IMultiTenant
+ {
+ // Properties shared with the IdentityRole class
+
+ public Guid? TenantId { get; private set; }
+ public string Name { get; private set; }
+
+ //Additional properties
+
+ public string Title { get; set; }
+
+ private AppRole()
+ {
+
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettingDefinitionProvider.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettingDefinitionProvider.cs
new file mode 100644
index 0000000000..6527dbc91f
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettingDefinitionProvider.cs
@@ -0,0 +1,13 @@
+using Volo.Abp.Settings;
+
+namespace Acme.BookStore.Settings
+{
+ public class BookStoreSettingDefinitionProvider : SettingDefinitionProvider
+ {
+ public override void Define(ISettingDefinitionContext context)
+ {
+ //Define your own settings here. Example:
+ //context.Add(new SettingDefinition(BookStoreSettings.MySetting1));
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettings.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettings.cs
new file mode 100644
index 0000000000..7d5aa84d19
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Settings/BookStoreSettings.cs
@@ -0,0 +1,10 @@
+namespace Acme.BookStore.Settings
+{
+ public static class BookStoreSettings
+ {
+ private const string Prefix = "BookStore";
+
+ //Add your own setting names here. Example:
+ //public const string MySetting1 = Prefix + ".MySetting1";
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs
new file mode 100644
index 0000000000..9068cfbcd5
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.Domain/Users/AppUser.cs
@@ -0,0 +1,53 @@
+using System;
+using Volo.Abp.Domain.Entities.Auditing;
+using Volo.Abp.Users;
+
+namespace Acme.BookStore.Users
+{
+ /* This entity shares the same table/collection ("AbpUsers" by default) with the
+ * IdentityUser entity of the Identity module.
+ *
+ * - You can define your custom properties into this class.
+ * - You never create or delete this entity, because it is Identity module's job.
+ * - You can query users from database with this entity.
+ * - You can update values of your custom properties.
+ */
+ public class AppUser : FullAuditedAggregateRoot, IUser
+ {
+ #region Base properties
+
+ /* These properties are shared with the IdentityUser entity of the Identity module.
+ * Do not change these properties through this class. Instead, use Identity module
+ * services (like IdentityUserManager) to change them.
+ * So, this properties are designed as read only!
+ */
+
+ public virtual Guid? TenantId { get; private set; }
+
+ public virtual string UserName { get; private set; }
+
+ public virtual string Name { get; private set; }
+
+ public virtual string Surname { get; private set; }
+
+ public virtual string Email { get; private set; }
+
+ public virtual bool EmailConfirmed { get; private set; }
+
+ public virtual string PhoneNumber { get; private set; }
+
+ public virtual bool PhoneNumberConfirmed { get; private set; }
+
+ #endregion
+
+ /* Add your own properties here. Example:
+ *
+ * public virtual string MyProperty { get; set; }
+ */
+
+ private AppUser()
+ {
+
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj
new file mode 100644
index 0000000000..b38c71d1d4
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Acme.BookStore.EntityFrameworkCore.DbMigrations.csproj
@@ -0,0 +1,18 @@
+
+
+
+
+
+ netcoreapp3.1
+ Acme.BookStore
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs
new file mode 100644
index 0000000000..88e21f2ce8
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreEntityFrameworkCoreDbMigrationsModule.cs
@@ -0,0 +1,16 @@
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Modularity;
+
+namespace Acme.BookStore.EntityFrameworkCore
+{
+ [DependsOn(
+ typeof(BookStoreEntityFrameworkCoreModule)
+ )]
+ public class BookStoreEntityFrameworkCoreDbMigrationsModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAbpDbContext();
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs
new file mode 100644
index 0000000000..43ee74bb33
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContext.cs
@@ -0,0 +1,61 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.FeatureManagement.EntityFrameworkCore;
+using Volo.Abp.Identity;
+using Volo.Abp.Identity.EntityFrameworkCore;
+using Volo.Abp.IdentityServer.EntityFrameworkCore;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.TenantManagement.EntityFrameworkCore;
+
+namespace Acme.BookStore.EntityFrameworkCore
+{
+ /* This DbContext is only used for database migrations.
+ * It is not used on runtime. See BookStoreDbContext for the runtime DbContext.
+ * It is a unified model that includes configuration for
+ * all used modules and your application.
+ */
+ public class BookStoreMigrationsDbContext : AbpDbContext
+ {
+ public BookStoreMigrationsDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ /* Include modules to your migration db context */
+
+ builder.ConfigurePermissionManagement();
+ builder.ConfigureSettingManagement();
+ builder.ConfigureBackgroundJobs();
+ builder.ConfigureAuditLogging();
+ builder.ConfigureIdentity();
+ builder.ConfigureIdentityServer();
+ builder.ConfigureFeatureManagement();
+ builder.ConfigureTenantManagement();
+
+ /* Configure customizations for entities from the modules included */
+
+ //CONFIGURE THE CUSTOM ROLE PROPERTIES
+ builder.Entity(b =>
+ {
+ b.ConfigureCustomRoleProperties();
+ });
+
+ builder.Entity(b =>
+ {
+ b.ConfigureCustomUserProperties();
+ });
+
+ /* Configure your own tables/entities inside the ConfigureBookStore method */
+
+ builder.ConfigureBookStore();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs
new file mode 100644
index 0000000000..da72e6fb21
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/BookStoreMigrationsDbContextFactory.cs
@@ -0,0 +1,31 @@
+using System.IO;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+
+namespace Acme.BookStore.EntityFrameworkCore
+{
+ /* This class is needed for EF Core console commands
+ * (like Add-Migration and Update-Database commands) */
+ public class BookStoreMigrationsDbContextFactory : IDesignTimeDbContextFactory
+ {
+ public BookStoreMigrationsDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+
+ var builder = new DbContextOptionsBuilder()
+ .UseSqlServer(configuration.GetConnectionString("Default"));
+
+ return new BookStoreMigrationsDbContext(builder.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+ }
+}
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs
new file mode 100644
index 0000000000..70406832b9
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/EntityFrameworkCore/EntityFrameworkCoreBookStoreDbSchemaMigrator.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Acme.BookStore.Data;
+using Volo.Abp.DependencyInjection;
+
+namespace Acme.BookStore.EntityFrameworkCore
+{
+ [Dependency(ReplaceServices = true)]
+ public class EntityFrameworkCoreBookStoreDbSchemaMigrator
+ : IBookStoreDbSchemaMigrator, ITransientDependency
+ {
+ private readonly IServiceProvider _serviceProvider;
+
+ public EntityFrameworkCoreBookStoreDbSchemaMigrator(
+ IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ public async Task MigrateAsync()
+ {
+ /* We intentionally resolving the BookStoreMigrationsDbContext
+ * from IServiceProvider (instead of directly injecting it)
+ * to properly get the connection string of the current tenant in the
+ * current scope.
+ */
+
+ await _serviceProvider
+ .GetRequiredService()
+ .Database
+ .MigrateAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs
new file mode 100644
index 0000000000..6448210e1e
--- /dev/null
+++ b/samples/EfCoreMigrationDemo/src/Acme.BookStore.EntityFrameworkCore.DbMigrations/Migrations/20200106080719_Initial.Designer.cs
@@ -0,0 +1,1761 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Acme.BookStore.EntityFrameworkCore;
+
+namespace Acme.BookStore.Migrations
+{
+ [DbContext(typeof(BookStoreMigrationsDbContext))]
+ [Migration("20200106080719_Initial")]
+ partial class Initial
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "3.1.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128)
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ApplicationName")
+ .HasColumnName("ApplicationName")
+ .HasColumnType("nvarchar(96)")
+ .HasMaxLength(96);
+
+ b.Property("BrowserInfo")
+ .HasColumnName("BrowserInfo")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("ClientId")
+ .HasColumnName("ClientId")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ClientIpAddress")
+ .HasColumnName("ClientIpAddress")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ClientName")
+ .HasColumnName("ClientName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Comments")
+ .HasColumnName("Comments")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ConcurrencyStamp")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CorrelationId")
+ .HasColumnName("CorrelationId")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("Exceptions")
+ .HasColumnName("Exceptions")
+ .HasColumnType("nvarchar(4000)")
+ .HasMaxLength(4000);
+
+ b.Property("ExecutionDuration")
+ .HasColumnName("ExecutionDuration")
+ .HasColumnType("int");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("HttpMethod")
+ .HasColumnName("HttpMethod")
+ .HasColumnType("nvarchar(16)")
+ .HasMaxLength(16);
+
+ b.Property("HttpStatusCode")
+ .HasColumnName("HttpStatusCode")
+ .HasColumnType("int");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnName("ImpersonatorTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnName("ImpersonatorUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Url")
+ .HasColumnName("Url")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("UserId")
+ .HasColumnName("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserName")
+ .HasColumnName("UserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ExecutionTime");
+
+ b.HasIndex("TenantId", "UserId", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogs");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnName("AuditLogId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ExecutionDuration")
+ .HasColumnName("ExecutionDuration")
+ .HasColumnType("int");
+
+ b.Property("ExecutionTime")
+ .HasColumnName("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("MethodName")
+ .HasColumnName("MethodName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Parameters")
+ .HasColumnName("Parameters")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ServiceName")
+ .HasColumnName("ServiceName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogActions");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnName("AuditLogId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ChangeTime")
+ .HasColumnName("ChangeTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ChangeType")
+ .HasColumnName("ChangeType")
+ .HasColumnType("tinyint");
+
+ b.Property("EntityId")
+ .IsRequired()
+ .HasColumnName("EntityId")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("EntityTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityTypeFullName")
+ .IsRequired()
+ .HasColumnName("EntityTypeFullName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "EntityTypeFullName", "EntityId");
+
+ b.ToTable("AbpEntityChanges");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityChangeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("NewValue")
+ .HasColumnName("NewValue")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("OriginalValue")
+ .HasColumnName("OriginalValue")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("PropertyName")
+ .IsRequired()
+ .HasColumnName("PropertyName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("PropertyTypeFullName")
+ .IsRequired()
+ .HasColumnName("PropertyTypeFullName")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeId");
+
+ b.ToTable("AbpEntityPropertyChanges");
+ });
+
+ modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsAbandoned")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("JobArgs")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)")
+ .HasMaxLength(1048576);
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("LastTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("NextTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Priority")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("tinyint")
+ .HasDefaultValue((byte)15);
+
+ b.Property("TryCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasDefaultValue((short)0);
+
+ b.HasKey("Id");
+
+ b.HasIndex("IsAbandoned", "NextTryTime");
+
+ b.ToTable("AbpBackgroundJobs");
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ProviderKey")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ProviderName")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name", "ProviderName", "ProviderKey");
+
+ b.ToTable("AbpFeatureValues");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("Regex")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("RegexDescription")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ValueType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpClaimTypes");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .IsRequired()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDefault")
+ .HasColumnName("IsDefault")
+ .HasColumnType("bit");
+
+ b.Property("IsPublic")
+ .HasColumnName("IsPublic")
+ .HasColumnType("bit");
+
+ b.Property("IsStatic")
+ .HasColumnName("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedName")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName");
+
+ b.ToTable("AbpRoles");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ClaimValue")
+ .HasColumnType("nvarchar(1024)")
+ .HasMaxLength(1024);
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AbpRoleClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AccessFailedCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("AccessFailedCount")
+ .HasColumnType("int")
+ .HasDefaultValue(0);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnName("Email")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("EmailConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("EmailConfirmed")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LockoutEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("LockoutEnabled")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LockoutEnd")
+ .HasColumnType("datetimeoffset");
+
+ b.Property("Name")
+ .HasColumnName("Name")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("NormalizedEmail")
+ .IsRequired()
+ .HasColumnName("NormalizedEmail")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedUserName")
+ .IsRequired()
+ .HasColumnName("NormalizedUserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("PasswordHash")
+ .HasColumnName("PasswordHash")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("PhoneNumber")
+ .HasColumnName("PhoneNumber")
+ .HasColumnType("nvarchar(16)")
+ .HasMaxLength(16);
+
+ b.Property("PhoneNumberConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("PhoneNumberConfirmed")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("SecurityStamp")
+ .IsRequired()
+ .HasColumnName("SecurityStamp")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("Surname")
+ .HasColumnName("Surname")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TwoFactorEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("TwoFactorEnabled")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnName("UserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("Email");
+
+ b.HasIndex("NormalizedEmail");
+
+ b.HasIndex("NormalizedUserName");
+
+ b.HasIndex("UserName");
+
+ b.ToTable("AbpUsers");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ClaimValue")
+ .HasColumnType("nvarchar(1024)")
+ .HasMaxLength(1024);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AbpUserClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ProviderKey")
+ .IsRequired()
+ .HasColumnType("nvarchar(196)")
+ .HasMaxLength(196);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("UserId", "LoginProvider");
+
+ b.HasIndex("LoginProvider", "ProviderKey");
+
+ b.ToTable("AbpUserLogins");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId", "UserId");
+
+ b.ToTable("AbpUserRoles");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AbpUserTokens");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Enabled")
+ .HasColumnType("bit");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("IdentityServerApiResources");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.HasKey("ApiResourceId", "Type");
+
+ b.ToTable("IdentityServerApiClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Emphasize")
+ .HasColumnType("bit");
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ShowInDiscoveryDocument")
+ .HasColumnType("bit");
+
+ b.HasKey("ApiResourceId", "Name");
+
+ b.ToTable("IdentityServerApiScopes");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.HasKey("ApiResourceId", "Name", "Type");
+
+ b.ToTable("IdentityServerApiScopeClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(250)")
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(4000)")
+ .HasMaxLength(4000);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("Expiration")
+ .HasColumnType("datetime2");
+
+ b.HasKey("ApiResourceId", "Type", "Value");
+
+ b.ToTable("IdentityServerApiSecrets");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AbsoluteRefreshTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("AccessTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("AccessTokenType")
+ .HasColumnType("int");
+
+ b.Property("AllowAccessTokensViaBrowser")
+ .HasColumnType("bit");
+
+ b.Property("AllowOfflineAccess")
+ .HasColumnType("bit");
+
+ b.Property("AllowPlainTextPkce")
+ .HasColumnType("bit");
+
+ b.Property("AllowRememberConsent")
+ .HasColumnType("bit");
+
+ b.Property("AlwaysIncludeUserClaimsInIdToken")
+ .HasColumnType("bit");
+
+ b.Property("AlwaysSendClientClaims")
+ .HasColumnType("bit");
+
+ b.Property("AuthorizationCodeLifetime")
+ .HasColumnType("int");
+
+ b.Property("BackChannelLogoutSessionRequired")
+ .HasColumnType("bit");
+
+ b.Property("BackChannelLogoutUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ClientClaimsPrefix")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientId")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ConsentLifetime")
+ .HasColumnType("int");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DeviceCodeLifetime")
+ .HasColumnType("int");
+
+ b.Property("EnableLocalLogin")
+ .HasColumnType("bit");
+
+ b.Property("Enabled")
+ .HasColumnType("bit");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("FrontChannelLogoutSessionRequired")
+ .HasColumnType("bit");
+
+ b.Property("FrontChannelLogoutUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("IdentityTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("IncludeJwtId")
+ .HasColumnType("bit");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LogoUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("PairWiseSubjectSalt")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ProtocolType")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("RefreshTokenExpiration")
+ .HasColumnType("int");
+
+ b.Property("RefreshTokenUsage")
+ .HasColumnType("int");
+
+ b.Property("RequireClientSecret")
+ .HasColumnType("bit");
+
+ b.Property("RequireConsent")
+ .HasColumnType("bit");
+
+ b.Property("RequirePkce")
+ .HasColumnType("bit");
+
+ b.Property("SlidingRefreshTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("UpdateAccessTokenClaimsOnRefresh")
+ .HasColumnType("bit");
+
+ b.Property("UserCodeType")
+ .HasColumnType("nvarchar(100)")
+ .HasMaxLength(100);
+
+ b.Property("UserSsoLifetime")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("IdentityServerClients");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(250)")
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(250)")
+ .HasMaxLength(250);
+
+ b.HasKey("ClientId", "Type", "Value");
+
+ b.ToTable("IdentityServerClientClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Origin")
+ .HasColumnType("nvarchar(150)")
+ .HasMaxLength(150);
+
+ b.HasKey("ClientId", "Origin");
+
+ b.ToTable("IdentityServerClientCorsOrigins");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("GrantType")
+ .HasColumnType("nvarchar(250)")
+ .HasMaxLength(250);
+
+ b.HasKey("ClientId", "GrantType");
+
+ b.ToTable("IdentityServerClientGrantTypes");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b =>
+ {
+ b.Property("ClientId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Provider")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.HasKey("ClientId", "Provider");
+
+ b.ToTable("IdentityServerClientIdPRestrictions");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b =>
+ {
+ b.Property