From aa82f08b3efd20d15096a932d6630f26721f319a Mon Sep 17 00:00:00 2001 From: dorthl Date: Thu, 8 Jun 2023 16:29:53 +0800 Subject: [PATCH 1/5] realize SQLite provider --- docs/02-Database.md | 4 +- src/Blogifier/Data/AppDbContext.cs | 36 +- .../20230602104208_Init.Designer.cs | 509 ------------------ .../Data/Migrations/20230602104208_Init.cs | 400 -------------- .../Data/Migrations/20230606095435_Storage.cs | 241 --------- .../20230608075855_Init.Designer.cs} | 197 +++---- .../Migrations/Sqlite/20230608075855_Init.cs | 386 +++++++++++++ .../SqliteDbContextModelSnapshot.cs} | 195 +++---- src/Blogifier/Data/SqliteDbContext.cs | 77 +++ .../UtcDateTimeValueGenerator .cs | 22 + src/Blogifier/Identity/UserInfo.cs | 2 +- src/Blogifier/Newsletters/Newsletter.cs | 2 - src/Blogifier/Newsletters/Subscriber.cs | 2 - src/Blogifier/Options/OptionInfo.cs | 3 - src/Blogifier/Posts/Category.cs | 1 - src/Blogifier/Posts/Post.cs | 3 - src/Blogifier/Program.cs | 20 +- src/Blogifier/Storages/Storage.cs | 1 - src/Blogifier/Storages/StorageReference.cs | 1 - testEnvironments.json | 17 - 20 files changed, 724 insertions(+), 1395 deletions(-) delete mode 100644 src/Blogifier/Data/Migrations/20230602104208_Init.Designer.cs delete mode 100644 src/Blogifier/Data/Migrations/20230602104208_Init.cs delete mode 100644 src/Blogifier/Data/Migrations/20230606095435_Storage.cs rename src/Blogifier/Data/Migrations/{20230606095435_Storage.Designer.cs => Sqlite/20230608075855_Init.Designer.cs} (73%) create mode 100644 src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs rename src/Blogifier/Data/Migrations/{AppDbContextModelSnapshot.cs => Sqlite/SqliteDbContextModelSnapshot.cs} (73%) create mode 100644 src/Blogifier/Data/SqliteDbContext.cs create mode 100644 src/Blogifier/Data/ValueGeneration/UtcDateTimeValueGenerator .cs delete mode 100644 testEnvironments.json diff --git a/docs/02-Database.md b/docs/02-Database.md index 87fef7c58..5f1608ea3 100644 --- a/docs/02-Database.md +++ b/docs/02-Database.md @@ -9,7 +9,7 @@ ... } ``` -Valid providers: `SQLite`, `SqlServer`, `Postgres`, `MySql` (you'll need to supply valid connection string) +Valid providers: `Sqlite`, `SqlServer`, `Postgres`, `MySql` (you'll need to supply valid connection string) 2. Remove `Blogifier/Data/Migrations` folder with existing migrations 3. In the Visual Studio, open `Package Manager Console`, set `Blogifier` @@ -22,6 +22,8 @@ Update-Database # cil dotnet ef migrations Init -o Data\Migrations dotnet ef migrations remove + +dotnet ef migrations add Init --context SqliteDbContext --output-dir Data/Migrations/Sqlite ``` First command should re-generate provider specific code migrations and second will diff --git a/src/Blogifier/Data/AppDbContext.cs b/src/Blogifier/Data/AppDbContext.cs index 5dbd45791..ce848c8df 100644 --- a/src/Blogifier/Data/AppDbContext.cs +++ b/src/Blogifier/Data/AppDbContext.cs @@ -11,21 +11,18 @@ namespace Blogifier.Data; public class AppDbContext : IdentityUserContext { - protected readonly DbContextOptions _options; - - public AppDbContext(DbContextOptions options) : base(options) + public AppDbContext(DbContextOptions options) : base(options) { - _options = options; - } + } public DbSet Options { get; set; } = default!; public DbSet Posts { get; set; } = default!; - public DbSet Storages { get; set; } = default!; - public DbSet StorageReferences { get; set; } = default!; public DbSet Categories { get; set; } = default!; public DbSet PostCategories { get; set; } = default!; - public DbSet Subscribers { get; set; } = default!; public DbSet Newsletters { get; set; } = default!; + public DbSet Subscribers { get; set; } = default!; + public DbSet Storages { get; set; } = default!; + public DbSet StorageReferences { get; set; } = default!; protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -36,6 +33,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) e.ToTable("User"); e.Property(p => p.Id).HasMaxLength(128); e.Property(p => p.CreatedAt).HasColumnOrder(0); + e.Property(p => p.UpdatedAt).HasColumnOrder(1); e.Property(p => p.PasswordHash).HasMaxLength(256); e.Property(p => p.SecurityStamp).HasMaxLength(32); e.Property(p => p.ConcurrencyStamp).HasMaxLength(64); @@ -65,6 +63,17 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) e.HasIndex(b => b.Key).IsUnique(); }); + modelBuilder.Entity(e => + { + e.ToTable("Post"); + e.HasIndex(b => b.Slug).IsUnique(); + + e.HasMany(e => e.StorageReferences) + .WithOne(e => e.Post) + .HasForeignKey(e => e.EntityId) + .IsRequired(); + }); + modelBuilder.Entity(e => { e.ToTable("StorageReferences"); @@ -76,16 +85,5 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) e.ToTable("PostCategories"); e.HasKey(t => new { t.PostId, t.CategoryId }); }); - - modelBuilder.Entity(e => - { - e.ToTable("Post"); - e.HasIndex(b => b.Slug).IsUnique(); - - e.HasMany(e => e.StorageReferences) - .WithOne(e => e.Post) - .HasForeignKey(e => e.EntityId) - .IsRequired(); - }); } } diff --git a/src/Blogifier/Data/Migrations/20230602104208_Init.Designer.cs b/src/Blogifier/Data/Migrations/20230602104208_Init.Designer.cs deleted file mode 100644 index 46e58dc6f..000000000 --- a/src/Blogifier/Data/Migrations/20230602104208_Init.Designer.cs +++ /dev/null @@ -1,509 +0,0 @@ -// -using System; -using Blogifier.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Blogifier.Data.Migrations -{ - [DbContext(typeof(AppDbContext))] - [Migration("20230602104208_Init")] - partial class Init - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Blogifier.Identity.UserInfo", b => - { - b.Property("Id") - .HasMaxLength(128) - .HasColumnType("varchar(128)"); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("Avatar") - .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); - - b.Property("Bio") - .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)") - .HasColumnOrder(0); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("Gender") - .HasMaxLength(32) - .HasColumnType("varchar(32)"); - - b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); - - b.Property("NickName") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PasswordHash") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("PhoneNumber") - .HasMaxLength(32) - .HasColumnType("varchar(32)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); - - b.Property("SecurityStamp") - .HasMaxLength(32) - .HasColumnType("varchar(32)"); - - b.Property("State") - .HasColumnType("int"); - - b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); - - b.Property("Type") - .HasColumnType("int"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex"); - - b.ToTable("User", (string)null); - }); - - modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("PostId") - .HasColumnType("int"); - - b.Property("Success") - .HasColumnType("tinyint(1)"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("PostId"); - - b.ToTable("Newsletters"); - }); - - modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Country") - .HasMaxLength(120) - .HasColumnType("varchar(120)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("Email") - .IsRequired() - .HasMaxLength(160) - .HasColumnType("varchar(160)"); - - b.Property("Ip") - .HasMaxLength(80) - .HasColumnType("varchar(80)"); - - b.Property("Region") - .HasMaxLength(120) - .HasColumnType("varchar(120)"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.ToTable("Subscribers"); - }); - - modelBuilder.Entity("Blogifier.Options.OptionInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("Key") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); - - b.Property("Value") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("Key") - .IsUnique(); - - b.ToTable("Options", (string)null); - }); - - modelBuilder.Entity("Blogifier.Shared.Category", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Content") - .IsRequired() - .HasMaxLength(120) - .HasColumnType("varchar(120)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("Description") - .HasMaxLength(255) - .HasColumnType("varchar(255)"); - - b.HasKey("Id"); - - b.ToTable("Categories"); - }); - - modelBuilder.Entity("Blogifier.Shared.Post", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Content") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Cover") - .HasMaxLength(160) - .HasColumnType("varchar(160)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("Description") - .IsRequired() - .HasMaxLength(450) - .HasColumnType("varchar(450)"); - - b.Property("PostType") - .HasColumnType("int"); - - b.Property("PublishedAt") - .HasColumnType("datetime(6)"); - - b.Property("Slug") - .IsRequired() - .HasMaxLength(160) - .HasColumnType("varchar(160)"); - - b.Property("State") - .HasColumnType("int"); - - b.Property("Title") - .IsRequired() - .HasMaxLength(160) - .HasColumnType("varchar(160)"); - - b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); - - b.Property("UserId") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("varchar(128)"); - - b.Property("Views") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("Posts"); - }); - - modelBuilder.Entity("Blogifier.Shared.PostCategory", b => - { - b.Property("PostId") - .HasColumnType("int"); - - b.Property("CategoryId") - .HasColumnType("int"); - - b.HasKey("PostId", "CategoryId"); - - b.HasIndex("CategoryId"); - - b.ToTable("PostCategories", (string)null); - }); - - modelBuilder.Entity("Blogifier.Shared.Storage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("AuthorId") - .HasColumnType("int"); - - b.Property("ContentType") - .IsRequired() - .HasMaxLength(128) - .HasColumnType("varchar(128)"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); - - b.Property("DeletedAt") - .HasColumnType("datetime(6)"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Length") - .HasColumnType("bigint"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); - - b.Property("StorageType") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("Storages"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ClaimType") - .HasMaxLength(16) - .HasColumnType("varchar(16)"); - - b.Property("ClaimValue") - .HasMaxLength(256) - .HasColumnType("varchar(256)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(128)"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("UserClaim", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("ProviderKey") - .HasColumnType("varchar(255)"); - - b.Property("ProviderDisplayName") - .HasMaxLength(128) - .HasColumnType("varchar(128)"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("varchar(128)"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("UserLogin", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("varchar(128)"); - - b.Property("LoginProvider") - .HasColumnType("varchar(255)"); - - b.Property("Name") - .HasColumnType("varchar(255)"); - - b.Property("Value") - .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("UserToken", (string)null); - }); - - modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => - { - b.HasOne("Blogifier.Shared.Post", "Post") - .WithMany() - .HasForeignKey("PostId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Post"); - }); - - modelBuilder.Entity("Blogifier.Shared.Post", b => - { - b.HasOne("Blogifier.Identity.UserInfo", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Blogifier.Shared.PostCategory", b => - { - b.HasOne("Blogifier.Shared.Category", "Category") - .WithMany("PostCategories") - .HasForeignKey("CategoryId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Blogifier.Shared.Post", "Post") - .WithMany("PostCategories") - .HasForeignKey("PostId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Category"); - - b.Navigation("Post"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Blogifier.Identity.UserInfo", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Blogifier.Identity.UserInfo", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Blogifier.Identity.UserInfo", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Blogifier.Shared.Category", b => - { - b.Navigation("PostCategories"); - }); - - modelBuilder.Entity("Blogifier.Shared.Post", b => - { - b.Navigation("PostCategories"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Blogifier/Data/Migrations/20230602104208_Init.cs b/src/Blogifier/Data/Migrations/20230602104208_Init.cs deleted file mode 100644 index e280ed4da..000000000 --- a/src/Blogifier/Data/Migrations/20230602104208_Init.cs +++ /dev/null @@ -1,400 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using System; - -#nullable disable - -namespace Blogifier.Data.Migrations -{ - /// - public partial class Init : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Categories", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Content = table.Column(type: "varchar(120)", maxLength: 120, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(255)", maxLength: 255, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Categories", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Options", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UpdatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), - Key = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Options", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Storages", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - AuthorId = table.Column(type: "int", nullable: false), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - DeletedAt = table.Column(type: "datetime(6)", nullable: true), - Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Path = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Length = table.Column(type: "bigint", nullable: false), - ContentType = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - StorageType = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Storages", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Subscribers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UpdatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), - Email = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Ip = table.Column(type: "varchar(80)", maxLength: 80, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Country = table.Column(type: "varchar(120)", maxLength: 120, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Region = table.Column(type: "varchar(120)", maxLength: 120, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Subscribers", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "User", - columns: table => new - { - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Id = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - NickName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Avatar = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Bio = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Gender = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Type = table.Column(type: "int", nullable: false), - State = table.Column(type: "int", nullable: false), - UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false), - PasswordHash = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - SecurityStamp = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ConcurrencyStamp = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumber = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false), - TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false), - LockoutEnd = table.Column(type: "datetime(6)", nullable: true), - LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false), - AccessFailedCount = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_User", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Posts", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UpdatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), - UserId = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Title = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Slug = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "varchar(450)", maxLength: 450, nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Content = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Cover = table.Column(type: "varchar(160)", maxLength: 160, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - Views = table.Column(type: "int", nullable: false), - PublishedAt = table.Column(type: "datetime(6)", nullable: true), - PostType = table.Column(type: "int", nullable: false), - State = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Posts", x => x.Id); - table.ForeignKey( - name: "FK_Posts_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "UserClaim", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UserId = table.Column(type: "varchar(128)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimType = table.Column(type: "varchar(16)", maxLength: 16, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - ClaimValue = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_UserClaim", x => x.Id); - table.ForeignKey( - name: "FK_UserClaim_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "UserLogin", - columns: table => new - { - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderKey = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProviderDisplayName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4"), - UserId = table.Column(type: "varchar(128)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); - table.ForeignKey( - name: "FK_UserLogin_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "UserToken", - columns: table => new - { - UserId = table.Column(type: "varchar(128)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - LoginProvider = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "varchar(255)", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Value = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); - table.ForeignKey( - name: "FK_UserToken_User_UserId", - column: x => x.UserId, - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Newsletters", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - UpdatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), - PostId = table.Column(type: "int", nullable: false), - Success = table.Column(type: "tinyint(1)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Newsletters", x => x.Id); - table.ForeignKey( - name: "FK_Newsletters_Posts_PostId", - column: x => x.PostId, - principalTable: "Posts", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "PostCategories", - columns: table => new - { - PostId = table.Column(type: "int", nullable: false), - CategoryId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PostCategories", x => new { x.PostId, x.CategoryId }); - table.ForeignKey( - name: "FK_PostCategories_Categories_CategoryId", - column: x => x.CategoryId, - principalTable: "Categories", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_PostCategories_Posts_PostId", - column: x => x.PostId, - principalTable: "Posts", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_Newsletters_PostId", - table: "Newsletters", - column: "PostId"); - - migrationBuilder.CreateIndex( - name: "IX_Options_Key", - table: "Options", - column: "Key", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_PostCategories_CategoryId", - table: "PostCategories", - column: "CategoryId"); - - migrationBuilder.CreateIndex( - name: "IX_Posts_UserId", - table: "Posts", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "EmailIndex", - table: "User", - column: "NormalizedEmail"); - - migrationBuilder.CreateIndex( - name: "UserNameIndex", - table: "User", - column: "NormalizedUserName", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_UserClaim_UserId", - table: "UserClaim", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_UserLogin_UserId", - table: "UserLogin", - column: "UserId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Newsletters"); - - migrationBuilder.DropTable( - name: "Options"); - - migrationBuilder.DropTable( - name: "PostCategories"); - - migrationBuilder.DropTable( - name: "Storages"); - - migrationBuilder.DropTable( - name: "Subscribers"); - - migrationBuilder.DropTable( - name: "UserClaim"); - - migrationBuilder.DropTable( - name: "UserLogin"); - - migrationBuilder.DropTable( - name: "UserToken"); - - migrationBuilder.DropTable( - name: "Categories"); - - migrationBuilder.DropTable( - name: "Posts"); - - migrationBuilder.DropTable( - name: "User"); - } - } -} diff --git a/src/Blogifier/Data/Migrations/20230606095435_Storage.cs b/src/Blogifier/Data/Migrations/20230606095435_Storage.cs deleted file mode 100644 index 8b561c8cc..000000000 --- a/src/Blogifier/Data/Migrations/20230606095435_Storage.cs +++ /dev/null @@ -1,241 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using System; - -#nullable disable - -namespace Blogifier.Data.Migrations -{ - /// - public partial class Storage : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Newsletters_Posts_PostId", - table: "Newsletters"); - - migrationBuilder.DropForeignKey( - name: "FK_PostCategories_Posts_PostId", - table: "PostCategories"); - - migrationBuilder.DropForeignKey( - name: "FK_Posts_User_UserId", - table: "Posts"); - - migrationBuilder.DropPrimaryKey( - name: "PK_Posts", - table: "Posts"); - - migrationBuilder.DropColumn( - name: "AuthorId", - table: "Storages"); - - migrationBuilder.RenameTable( - name: "Posts", - newName: "Post"); - - migrationBuilder.RenameColumn( - name: "StorageType", - table: "Storages", - newName: "Type"); - - migrationBuilder.RenameIndex( - name: "IX_Posts_UserId", - table: "Post", - newName: "IX_Post_UserId"); - - migrationBuilder.AddColumn( - name: "Slug", - table: "Storages", - type: "varchar(2048)", - maxLength: 2048, - nullable: false, - defaultValue: "") - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "UserId", - table: "Storages", - type: "varchar(128)", - nullable: false, - defaultValue: "") - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddPrimaryKey( - name: "PK_Post", - table: "Post", - column: "Id"); - - migrationBuilder.CreateTable( - name: "StorageReferences", - columns: table => new - { - StorageId = table.Column(type: "int", nullable: false), - EntityId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "int", nullable: false), - CreatedAt = table.Column(type: "datetime(6)", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) - }, - constraints: table => - { - table.PrimaryKey("PK_StorageReferences", x => new { x.StorageId, x.EntityId, x.Type }); - table.ForeignKey( - name: "FK_StorageReferences_Post_EntityId", - column: x => x.EntityId, - principalTable: "Post", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_StorageReferences_Storages_StorageId", - column: x => x.StorageId, - principalTable: "Storages", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_Storages_UserId", - table: "Storages", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_Post_Slug", - table: "Post", - column: "Slug", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_StorageReferences_EntityId", - table: "StorageReferences", - column: "EntityId"); - - migrationBuilder.AddForeignKey( - name: "FK_Newsletters_Post_PostId", - table: "Newsletters", - column: "PostId", - principalTable: "Post", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Post_User_UserId", - table: "Post", - column: "UserId", - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_PostCategories_Post_PostId", - table: "PostCategories", - column: "PostId", - principalTable: "Post", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Storages_User_UserId", - table: "Storages", - column: "UserId", - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Newsletters_Post_PostId", - table: "Newsletters"); - - migrationBuilder.DropForeignKey( - name: "FK_Post_User_UserId", - table: "Post"); - - migrationBuilder.DropForeignKey( - name: "FK_PostCategories_Post_PostId", - table: "PostCategories"); - - migrationBuilder.DropForeignKey( - name: "FK_Storages_User_UserId", - table: "Storages"); - - migrationBuilder.DropTable( - name: "StorageReferences"); - - migrationBuilder.DropIndex( - name: "IX_Storages_UserId", - table: "Storages"); - - migrationBuilder.DropPrimaryKey( - name: "PK_Post", - table: "Post"); - - migrationBuilder.DropIndex( - name: "IX_Post_Slug", - table: "Post"); - - migrationBuilder.DropColumn( - name: "Slug", - table: "Storages"); - - migrationBuilder.DropColumn( - name: "UserId", - table: "Storages"); - - migrationBuilder.RenameTable( - name: "Post", - newName: "Posts"); - - migrationBuilder.RenameColumn( - name: "Type", - table: "Storages", - newName: "StorageType"); - - migrationBuilder.RenameIndex( - name: "IX_Post_UserId", - table: "Posts", - newName: "IX_Posts_UserId"); - - migrationBuilder.AddColumn( - name: "AuthorId", - table: "Storages", - type: "int", - nullable: false, - defaultValue: 0); - - migrationBuilder.AddPrimaryKey( - name: "PK_Posts", - table: "Posts", - column: "Id"); - - migrationBuilder.AddForeignKey( - name: "FK_Newsletters_Posts_PostId", - table: "Newsletters", - column: "PostId", - principalTable: "Posts", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_PostCategories_Posts_PostId", - table: "PostCategories", - column: "PostId", - principalTable: "Posts", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Posts_User_UserId", - table: "Posts", - column: "UserId", - principalTable: "User", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - } -} diff --git a/src/Blogifier/Data/Migrations/20230606095435_Storage.Designer.cs b/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs similarity index 73% rename from src/Blogifier/Data/Migrations/20230606095435_Storage.Designer.cs rename to src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs index 26459d812..dd78f729d 100644 --- a/src/Blogifier/Data/Migrations/20230606095435_Storage.Designer.cs +++ b/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs @@ -8,104 +8,108 @@ #nullable disable -namespace Blogifier.Data.Migrations +namespace Blogifier.Data.Migrations.Sqlite { - [DbContext(typeof(AppDbContext))] - [Migration("20230606095435_Storage")] - partial class Storage + [DbContext(typeof(SqliteDbContext))] + [Migration("20230608075855_Init")] + partial class Init { /// protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); + modelBuilder.HasAnnotation("ProductVersion", "7.0.5"); modelBuilder.Entity("Blogifier.Identity.UserInfo", b => { b.Property("Id") .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("AccessFailedCount") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Avatar") .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); + .HasColumnType("TEXT"); b.Property("Bio") .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)") - .HasColumnOrder(0); + .HasColumnType("TEXT") + .HasColumnOrder(0) + .HasDefaultValueSql("datetime()"); b.Property("Email") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Gender") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("NickName") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("NormalizedEmail") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("NormalizedUserName") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("PasswordHash") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("PhoneNumber") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("SecurityStamp") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("State") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("TEXT") + .HasColumnOrder(1); b.Property("UserName") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -123,21 +127,22 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("PostId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Success") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -150,32 +155,33 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Country") .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Email") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("Ip") .HasMaxLength(80) - .HasColumnType("varchar(80)"); + .HasColumnType("TEXT"); b.Property("Region") .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -186,24 +192,25 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Key") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("Value") .IsRequired() - .HasColumnType("longtext"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -217,20 +224,21 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Content") .IsRequired() .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Description") .HasMaxLength(255) - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -241,55 +249,56 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Content") .IsRequired() - .HasColumnType("longtext"); + .HasColumnType("TEXT"); b.Property("Cover") .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Description") .IsRequired() .HasMaxLength(450) - .HasColumnType("varchar(450)"); + .HasColumnType("TEXT"); b.Property("PostType") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("PublishedAt") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("Slug") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("State") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Title") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("Views") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -304,10 +313,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Shared.PostCategory", b => { b.Property("PostId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CategoryId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.HasKey("PostId", "CategoryId"); @@ -320,47 +329,48 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("ContentType") .IsRequired() .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("DeletedAt") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Length") - .HasColumnType("bigint"); + .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("Path") .IsRequired() .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("Slug") .IsRequired() .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -372,17 +382,18 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Storages.StorageReference", b => { b.Property("StorageId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("EntityId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.HasKey("StorageId", "EntityId", "Type"); @@ -395,19 +406,19 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("ClaimType") .HasMaxLength(16) - .HasColumnType("varchar(16)"); + .HasColumnType("TEXT"); b.Property("ClaimValue") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -419,18 +430,18 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("ProviderKey") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("ProviderDisplayName") .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("LoginProvider", "ProviderKey"); @@ -442,17 +453,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("LoginProvider") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("Name") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("Value") .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); + .HasColumnType("TEXT"); b.HasKey("UserId", "LoginProvider", "Name"); diff --git a/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs b/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs new file mode 100644 index 000000000..b5f9d20e8 --- /dev/null +++ b/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs @@ -0,0 +1,386 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Blogifier.Data.Migrations.Sqlite +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Categories", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + Content = table.Column(type: "TEXT", maxLength: 120, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Categories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Options", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + Key = table.Column(type: "TEXT", maxLength: 256, nullable: false), + Value = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Options", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Subscribers", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + Email = table.Column(type: "TEXT", maxLength: 160, nullable: false), + Ip = table.Column(type: "TEXT", maxLength: 80, nullable: true), + Country = table.Column(type: "TEXT", maxLength: 120, nullable: true), + Region = table.Column(type: "TEXT", maxLength: 120, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscribers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + Id = table.Column(type: "TEXT", maxLength: 128, nullable: false), + NickName = table.Column(type: "TEXT", maxLength: 256, nullable: false), + Avatar = table.Column(type: "TEXT", maxLength: 1024, nullable: true), + Bio = table.Column(type: "TEXT", maxLength: 2048, nullable: true), + Gender = table.Column(type: "TEXT", maxLength: 32, nullable: true), + Type = table.Column(type: "INTEGER", nullable: false), + State = table.Column(type: "INTEGER", nullable: false), + UserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "TEXT", maxLength: 256, nullable: true), + Email = table.Column(type: "TEXT", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "TEXT", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "INTEGER", nullable: false), + PasswordHash = table.Column(type: "TEXT", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "TEXT", maxLength: 32, nullable: true), + ConcurrencyStamp = table.Column(type: "TEXT", maxLength: 64, nullable: true), + PhoneNumber = table.Column(type: "TEXT", maxLength: 32, nullable: true), + PhoneNumberConfirmed = table.Column(type: "INTEGER", nullable: false), + TwoFactorEnabled = table.Column(type: "INTEGER", nullable: false), + LockoutEnd = table.Column(type: "TEXT", nullable: true), + LockoutEnabled = table.Column(type: "INTEGER", nullable: false), + AccessFailedCount = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Post", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + UserId = table.Column(type: "TEXT", maxLength: 128, nullable: false), + Title = table.Column(type: "TEXT", maxLength: 160, nullable: false), + Slug = table.Column(type: "TEXT", maxLength: 160, nullable: false), + Description = table.Column(type: "TEXT", maxLength: 450, nullable: false), + Content = table.Column(type: "TEXT", nullable: false), + Cover = table.Column(type: "TEXT", maxLength: 160, nullable: true), + Views = table.Column(type: "INTEGER", nullable: false), + PublishedAt = table.Column(type: "TEXT", nullable: true), + PostType = table.Column(type: "INTEGER", nullable: false), + State = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Post", x => x.Id); + table.ForeignKey( + name: "FK_Post_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Storages", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + IsDeleted = table.Column(type: "INTEGER", nullable: false), + DeletedAt = table.Column(type: "TEXT", nullable: true), + Slug = table.Column(type: "TEXT", maxLength: 2048, nullable: false), + Name = table.Column(type: "TEXT", maxLength: 256, nullable: false), + Path = table.Column(type: "TEXT", maxLength: 2048, nullable: false), + Length = table.Column(type: "INTEGER", nullable: false), + ContentType = table.Column(type: "TEXT", maxLength: 128, nullable: false), + Type = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Storages", x => x.Id); + table.ForeignKey( + name: "FK_Storages_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserClaim", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + UserId = table.Column(type: "TEXT", nullable: false), + ClaimType = table.Column(type: "TEXT", maxLength: 16, nullable: true), + ClaimValue = table.Column(type: "TEXT", maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserClaim_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(type: "TEXT", nullable: false), + ProviderKey = table.Column(type: "TEXT", nullable: false), + ProviderDisplayName = table.Column(type: "TEXT", maxLength: 128, nullable: true), + UserId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogin_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(type: "TEXT", nullable: false), + LoginProvider = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: false), + Value = table.Column(type: "TEXT", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserToken_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Newsletters", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()"), + UpdatedAt = table.Column(type: "TEXT", nullable: false), + PostId = table.Column(type: "INTEGER", nullable: false), + Success = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Newsletters", x => x.Id); + table.ForeignKey( + name: "FK_Newsletters_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PostCategories", + columns: table => new + { + PostId = table.Column(type: "INTEGER", nullable: false), + CategoryId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PostCategories", x => new { x.PostId, x.CategoryId }); + table.ForeignKey( + name: "FK_PostCategories_Categories_CategoryId", + column: x => x.CategoryId, + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PostCategories_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "StorageReferences", + columns: table => new + { + StorageId = table.Column(type: "INTEGER", nullable: false), + EntityId = table.Column(type: "INTEGER", nullable: false), + Type = table.Column(type: "INTEGER", nullable: false), + CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()") + }, + constraints: table => + { + table.PrimaryKey("PK_StorageReferences", x => new { x.StorageId, x.EntityId, x.Type }); + table.ForeignKey( + name: "FK_StorageReferences_Post_EntityId", + column: x => x.EntityId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_StorageReferences_Storages_StorageId", + column: x => x.StorageId, + principalTable: "Storages", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Newsletters_PostId", + table: "Newsletters", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_Options_Key", + table: "Options", + column: "Key", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_Slug", + table: "Post", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_UserId", + table: "Post", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_PostCategories_CategoryId", + table: "PostCategories", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_StorageReferences_EntityId", + table: "StorageReferences", + column: "EntityId"); + + migrationBuilder.CreateIndex( + name: "IX_Storages_UserId", + table: "Storages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserClaim_UserId", + table: "UserClaim", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogin_UserId", + table: "UserLogin", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Newsletters"); + + migrationBuilder.DropTable( + name: "Options"); + + migrationBuilder.DropTable( + name: "PostCategories"); + + migrationBuilder.DropTable( + name: "StorageReferences"); + + migrationBuilder.DropTable( + name: "Subscribers"); + + migrationBuilder.DropTable( + name: "UserClaim"); + + migrationBuilder.DropTable( + name: "UserLogin"); + + migrationBuilder.DropTable( + name: "UserToken"); + + migrationBuilder.DropTable( + name: "Categories"); + + migrationBuilder.DropTable( + name: "Post"); + + migrationBuilder.DropTable( + name: "Storages"); + + migrationBuilder.DropTable( + name: "User"); + } + } +} diff --git a/src/Blogifier/Data/Migrations/AppDbContextModelSnapshot.cs b/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs similarity index 73% rename from src/Blogifier/Data/Migrations/AppDbContextModelSnapshot.cs rename to src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs index d8aeb9266..4d5476a47 100644 --- a/src/Blogifier/Data/Migrations/AppDbContextModelSnapshot.cs +++ b/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs @@ -7,102 +7,106 @@ #nullable disable -namespace Blogifier.Data.Migrations +namespace Blogifier.Data.Migrations.Sqlite { - [DbContext(typeof(AppDbContext))] - partial class AppDbContextModelSnapshot : ModelSnapshot + [DbContext(typeof(SqliteDbContext))] + partial class SqliteDbContextModelSnapshot : ModelSnapshot { protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.5") - .HasAnnotation("Relational:MaxIdentifierLength", 64); + modelBuilder.HasAnnotation("ProductVersion", "7.0.5"); modelBuilder.Entity("Blogifier.Identity.UserInfo", b => { b.Property("Id") .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("AccessFailedCount") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Avatar") .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); + .HasColumnType("TEXT"); b.Property("Bio") .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)") - .HasColumnOrder(0); + .HasColumnType("TEXT") + .HasColumnOrder(0) + .HasDefaultValueSql("datetime()"); b.Property("Email") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("EmailConfirmed") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Gender") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("LockoutEnabled") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("LockoutEnd") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("NickName") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("NormalizedEmail") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("NormalizedUserName") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("PasswordHash") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("PhoneNumber") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("PhoneNumberConfirmed") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("SecurityStamp") .HasMaxLength(32) - .HasColumnType("varchar(32)"); + .HasColumnType("TEXT"); b.Property("State") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("TwoFactorEnabled") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("TEXT") + .HasColumnOrder(1); b.Property("UserName") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -120,21 +124,22 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("PostId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Success") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -147,32 +152,33 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Country") .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Email") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("Ip") .HasMaxLength(80) - .HasColumnType("varchar(80)"); + .HasColumnType("TEXT"); b.Property("Region") .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -183,24 +189,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Key") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("Value") .IsRequired() - .HasColumnType("longtext"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -214,20 +221,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Content") .IsRequired() .HasMaxLength(120) - .HasColumnType("varchar(120)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Description") .HasMaxLength(255) - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -238,55 +246,56 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Content") .IsRequired() - .HasColumnType("longtext"); + .HasColumnType("TEXT"); b.Property("Cover") .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("Description") .IsRequired() .HasMaxLength(450) - .HasColumnType("varchar(450)"); + .HasColumnType("TEXT"); b.Property("PostType") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("PublishedAt") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("Slug") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("State") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Title") .IsRequired() .HasMaxLength(160) - .HasColumnType("varchar(160)"); + .HasColumnType("TEXT"); b.Property("UpdatedAt") .ValueGeneratedOnAddOrUpdate() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("Views") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.HasKey("Id"); @@ -301,10 +310,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Shared.PostCategory", b => { b.Property("PostId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CategoryId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.HasKey("PostId", "CategoryId"); @@ -317,47 +326,48 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("ContentType") .IsRequired() .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.Property("DeletedAt") - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT"); b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); + .HasColumnType("INTEGER"); b.Property("Length") - .HasColumnType("bigint"); + .HasColumnType("INTEGER"); b.Property("Name") .IsRequired() .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("Path") .IsRequired() .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("Slug") .IsRequired() .HasMaxLength(2048) - .HasColumnType("varchar(2048)"); + .HasColumnType("TEXT"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -369,17 +379,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Storages.StorageReference", b => { b.Property("StorageId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("EntityId") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("Type") - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("CreatedAt") .ValueGeneratedOnAdd() - .HasColumnType("datetime(6)"); + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime()"); b.HasKey("StorageId", "EntityId", "Type"); @@ -392,19 +403,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("int"); + .HasColumnType("INTEGER"); b.Property("ClaimType") .HasMaxLength(16) - .HasColumnType("varchar(16)"); + .HasColumnType("TEXT"); b.Property("ClaimValue") .HasMaxLength(256) - .HasColumnType("varchar(256)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("Id"); @@ -416,18 +427,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("ProviderKey") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("ProviderDisplayName") .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("UserId") .IsRequired() - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.HasKey("LoginProvider", "ProviderKey"); @@ -439,17 +450,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") - .HasColumnType("varchar(128)"); + .HasColumnType("TEXT"); b.Property("LoginProvider") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("Name") - .HasColumnType("varchar(255)"); + .HasColumnType("TEXT"); b.Property("Value") .HasMaxLength(1024) - .HasColumnType("varchar(1024)"); + .HasColumnType("TEXT"); b.HasKey("UserId", "LoginProvider", "Name"); diff --git a/src/Blogifier/Data/SqliteDbContext.cs b/src/Blogifier/Data/SqliteDbContext.cs new file mode 100644 index 000000000..5b863f9ff --- /dev/null +++ b/src/Blogifier/Data/SqliteDbContext.cs @@ -0,0 +1,77 @@ +using Blogifier.Data.ValueGeneration; +using Blogifier.Identity; +using Blogifier.Newsletters; +using Blogifier.Options; +using Blogifier.Shared; +using Blogifier.Storages; +using Microsoft.EntityFrameworkCore; + +namespace Blogifier.Data; + +public class SqliteDbContext : AppDbContext +{ + public SqliteDbContext(DbContextOptions options) : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + + // https://github.com/dotnet/EntityFramework.Docs/issues/3057 + // https://github.com/dotnet/efcore/issues/19765 + // TOTO No solution has been found + // This configuration is not updated when the entity is updated + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + }); + + } +} diff --git a/src/Blogifier/Data/ValueGeneration/UtcDateTimeValueGenerator .cs b/src/Blogifier/Data/ValueGeneration/UtcDateTimeValueGenerator .cs new file mode 100644 index 000000000..8ac0ce84f --- /dev/null +++ b/src/Blogifier/Data/ValueGeneration/UtcDateTimeValueGenerator .cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.ChangeTracking; +using Microsoft.EntityFrameworkCore.ValueGeneration; +using System; +using System.Threading.Tasks; +using System.Threading; + +namespace Blogifier.Data.ValueGeneration; + +public class DateTimetValueGenerator : ValueGenerator +{ + public override bool GeneratesTemporaryValues => false; + + public override DateTime Next(EntityEntry entry) + { + return DateTime.UtcNow; + } + + public override ValueTask NextAsync(EntityEntry entry, CancellationToken cancellationToken = default) + { + return ValueTask.FromResult(DateTime.UtcNow); + } +} diff --git a/src/Blogifier/Identity/UserInfo.cs b/src/Blogifier/Identity/UserInfo.cs index 083533263..de00c0d9e 100644 --- a/src/Blogifier/Identity/UserInfo.cs +++ b/src/Blogifier/Identity/UserInfo.cs @@ -19,8 +19,8 @@ public UserInfo(string userName) : base() UserName = userName; } - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } + public DateTime UpdatedAt { get; set; } [StringLength(256)] public string NickName { get; set; } = default!; [StringLength(1024)] diff --git a/src/Blogifier/Newsletters/Newsletter.cs b/src/Blogifier/Newsletters/Newsletter.cs index 6bf25cfa1..c04b4fd27 100644 --- a/src/Blogifier/Newsletters/Newsletter.cs +++ b/src/Blogifier/Newsletters/Newsletter.cs @@ -7,9 +7,7 @@ namespace Blogifier.Newsletters; public class Newsletter : AppEntity { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime UpdatedAt { get; set; } public int PostId { get; set; } public bool Success { get; set; } diff --git a/src/Blogifier/Newsletters/Subscriber.cs b/src/Blogifier/Newsletters/Subscriber.cs index 849e10a05..6b8ae5906 100644 --- a/src/Blogifier/Newsletters/Subscriber.cs +++ b/src/Blogifier/Newsletters/Subscriber.cs @@ -7,9 +7,7 @@ namespace Blogifier.Newsletters; public class Subscriber : AppEntity { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime UpdatedAt { get; set; } [EmailAddress] [StringLength(160)] diff --git a/src/Blogifier/Options/OptionInfo.cs b/src/Blogifier/Options/OptionInfo.cs index 9b01294f8..03fce7439 100644 --- a/src/Blogifier/Options/OptionInfo.cs +++ b/src/Blogifier/Options/OptionInfo.cs @@ -1,6 +1,5 @@ using System; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; namespace Blogifier.Options; @@ -8,9 +7,7 @@ public class OptionInfo { [Key] public int Id { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime UpdatedAt { get; set; } [StringLength(256)] public string Key { get; set; } = default!; diff --git a/src/Blogifier/Posts/Category.cs b/src/Blogifier/Posts/Category.cs index 22561545e..8d8cca2c5 100644 --- a/src/Blogifier/Posts/Category.cs +++ b/src/Blogifier/Posts/Category.cs @@ -8,7 +8,6 @@ namespace Blogifier.Shared; public class Category : AppEntity { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } [StringLength(120)] public string Content { get; set; } = default!; diff --git a/src/Blogifier/Posts/Post.cs b/src/Blogifier/Posts/Post.cs index ac6560142..69692a055 100644 --- a/src/Blogifier/Posts/Post.cs +++ b/src/Blogifier/Posts/Post.cs @@ -4,15 +4,12 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; namespace Blogifier.Shared; public class Post : AppEntity { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } - [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime UpdatedAt { get; set; } [StringLength(128)] public string UserId { get; set; } = default!; diff --git a/src/Blogifier/Program.cs b/src/Blogifier/Program.cs index 07a22d1e5..01c786f4e 100644 --- a/src/Blogifier/Program.cs +++ b/src/Blogifier/Program.cs @@ -57,15 +57,17 @@ builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader())); var section = builder.Configuration.GetSection("Blogifier"); -var conn = section.GetValue("ConnString"); -if (section.GetValue("DbProvider") == "SQLite") - builder.Services.AddDbContext(o => o.UseSqlite(conn)); -else if (section.GetValue("DbProvider") == "SqlServer") - builder.Services.AddDbContext(o => o.UseSqlServer(conn)); -else if (section.GetValue("DbProvider") == "Postgres") - builder.Services.AddDbContext(o => o.UseNpgsql(conn)); -else if (section.GetValue("DbProvider") == "MySql") - builder.Services.AddDbContext(o => o.UseMySql(conn, ServerVersion.AutoDetect(conn))); +var provider = section.GetValue("DbProvider"); +var connectionString = section.GetValue("ConnString"); + +if ("Sqlite".Equals(provider, StringComparison.OrdinalIgnoreCase)) +{ + builder.Services.AddDbContext(o => o.UseSqlite(connectionString)); +} +else +{ + throw new Exception($"Unsupported provider: {provider}"); +} if (builder.Environment.IsDevelopment()) builder.Services.AddDatabaseDeveloperPageExceptionFilter(); diff --git a/src/Blogifier/Storages/Storage.cs b/src/Blogifier/Storages/Storage.cs index e36f8a76d..9671c8017 100644 --- a/src/Blogifier/Storages/Storage.cs +++ b/src/Blogifier/Storages/Storage.cs @@ -13,7 +13,6 @@ public class Storage public int Id { get; set; } public string UserId { get; set; } = default!; public UserInfo User { get; set; } = default!; - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } public bool IsDeleted { get; set; } public DateTime? DeletedAt { get; set; } diff --git a/src/Blogifier/Storages/StorageReference.cs b/src/Blogifier/Storages/StorageReference.cs index b488fa2e1..78dc3415b 100644 --- a/src/Blogifier/Storages/StorageReference.cs +++ b/src/Blogifier/Storages/StorageReference.cs @@ -6,7 +6,6 @@ namespace Blogifier.Storages; public class StorageReference { - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public DateTime CreatedAt { get; set; } public int StorageId { get; set; } public Storage Storage { get; set; } = default!; diff --git a/testEnvironments.json b/testEnvironments.json deleted file mode 100644 index 2c5e92936..000000000 --- a/testEnvironments.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "version": "1", - "environments": [ - // 请参阅 https://aka.ms/remotetesting 获取更多信息 - // 了解如何配置远程环境。 - //{ - // "name": "WSL Ubuntu", - // "type": "wsl", - // "wslDistribution": "Ubuntu" - //}, - //{ - // "name": "Docker dotnet/sdk", - // "type": "docker", - // "dockerImage": "mcr.microsoft.com/dotnet/sdk" - //} - ] -} \ No newline at end of file From 0b4dd12cf2c5dca6305493aadf1a7de4aa9e9801 Mon Sep 17 00:00:00 2001 From: dorthl Date: Thu, 8 Jun 2023 17:20:52 +0800 Subject: [PATCH 2/5] realize SqlServer provider --- docs/02-Database.md | 1 + .../Pages/Blogs/EditorView.razor | 2 +- src/Blogifier/Data/AppDbContext.cs | 17 +- .../SqlServer/20230608091513_Init.Designer.cs | 561 ++++++++++++++++++ .../SqlServer/20230608091513_Init.cs | 353 +++++++++++ .../SqlServerDbContextModelSnapshot.cs | 558 +++++++++++++++++ ...ner.cs => 20230608090804_Init.Designer.cs} | 56 +- ...8075855_Init.cs => 20230608090804_Init.cs} | 36 +- .../Sqlite/SqliteDbContextModelSnapshot.cs | 54 -- src/Blogifier/Data/SqlServerDbContext.cs | 75 +++ src/Blogifier/Data/SqliteDbContext.cs | 8 +- src/Blogifier/Posts/Post.cs | 2 +- src/Blogifier/Posts/PostProvider.cs | 2 +- src/Blogifier/Profiles/PostProfile.cs | 5 +- src/Blogifier/Profiles/StorageProfile.cs | 6 +- src/Blogifier/Program.cs | 4 + src/Blogifier/Storages/Storage.cs | 2 +- src/Blogifier/Storages/StorageReference.cs | 19 +- src/Blogifier/appsettings.json | 4 +- 19 files changed, 1585 insertions(+), 180 deletions(-) create mode 100644 src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.Designer.cs create mode 100644 src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.cs create mode 100644 src/Blogifier/Data/Migrations/SqlServer/SqlServerDbContextModelSnapshot.cs rename src/Blogifier/Data/Migrations/Sqlite/{20230608075855_Init.Designer.cs => 20230608090804_Init.Designer.cs} (89%) rename src/Blogifier/Data/Migrations/Sqlite/{20230608075855_Init.cs => 20230608090804_Init.cs} (91%) create mode 100644 src/Blogifier/Data/SqlServerDbContext.cs diff --git a/docs/02-Database.md b/docs/02-Database.md index 5f1608ea3..2cc6f5f73 100644 --- a/docs/02-Database.md +++ b/docs/02-Database.md @@ -24,6 +24,7 @@ dotnet ef migrations Init -o Data\Migrations dotnet ef migrations remove dotnet ef migrations add Init --context SqliteDbContext --output-dir Data/Migrations/Sqlite +dotnet ef migrations add Init --context SqlServerDbContext --output-dir Data/Migrations/SqlServer ``` First command should re-generate provider specific code migrations and second will diff --git a/src/Blogifier.Admin/Pages/Blogs/EditorView.razor b/src/Blogifier.Admin/Pages/Blogs/EditorView.razor index 861dfe9b8..893a547f6 100644 --- a/src/Blogifier.Admin/Pages/Blogs/EditorView.razor +++ b/src/Blogifier.Admin/Pages/Blogs/EditorView.razor @@ -31,7 +31,7 @@ @_localizer["delete"] - + diff --git a/src/Blogifier/Data/AppDbContext.cs b/src/Blogifier/Data/AppDbContext.cs index ce848c8df..e571ab06b 100644 --- a/src/Blogifier/Data/AppDbContext.cs +++ b/src/Blogifier/Data/AppDbContext.cs @@ -22,7 +22,7 @@ public AppDbContext(DbContextOptions options) : base(options) public DbSet Newsletters { get; set; } = default!; public DbSet Subscribers { get; set; } = default!; public DbSet Storages { get; set; } = default!; - public DbSet StorageReferences { get; set; } = default!; + //public DbSet StorageReferences { get; set; } = default!; protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -67,18 +67,13 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) { e.ToTable("Post"); e.HasIndex(b => b.Slug).IsUnique(); - - e.HasMany(e => e.StorageReferences) - .WithOne(e => e.Post) - .HasForeignKey(e => e.EntityId) - .IsRequired(); }); - modelBuilder.Entity(e => - { - e.ToTable("StorageReferences"); - e.HasKey(t => new { t.StorageId, t.EntityId, t.Type }); - }); + //modelBuilder.Entity(e => + //{ + // e.ToTable("StorageReferences"); + // e.HasKey(t => new { t.StorageId, t.EntityId }); + //}); modelBuilder.Entity(e => { diff --git a/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.Designer.cs b/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.Designer.cs new file mode 100644 index 000000000..9fcd3e73c --- /dev/null +++ b/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.Designer.cs @@ -0,0 +1,561 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Blogifier.Data.Migrations.SqlServer +{ + [DbContext(typeof(SqlServerDbContext))] + [Migration("20230608091513_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(0) + .HasDefaultValueSql("getdate()"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("Success") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("PostType") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime2"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("int"); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(128)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.cs b/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.cs new file mode 100644 index 000000000..4d51c4771 --- /dev/null +++ b/src/Blogifier/Data/Migrations/SqlServer/20230608091513_Init.cs @@ -0,0 +1,353 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Blogifier.Data.Migrations.SqlServer +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Categories", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + Content = table.Column(type: "nvarchar(120)", maxLength: 120, nullable: false), + Description = table.Column(type: "nvarchar(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Categories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Options", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + UpdatedAt = table.Column(type: "datetime2", nullable: false), + Key = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Value = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Options", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Subscribers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + UpdatedAt = table.Column(type: "datetime2", nullable: false), + Email = table.Column(type: "nvarchar(160)", maxLength: 160, nullable: false), + Ip = table.Column(type: "nvarchar(80)", maxLength: 80, nullable: true), + Country = table.Column(type: "nvarchar(120)", maxLength: 120, nullable: true), + Region = table.Column(type: "nvarchar(120)", maxLength: 120, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscribers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + UpdatedAt = table.Column(type: "datetime2", nullable: false), + Id = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + NickName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Avatar = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true), + Bio = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: true), + Gender = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: true), + Type = table.Column(type: "int", nullable: false), + State = table.Column(type: "int", nullable: false), + UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "bit", nullable: false), + PasswordHash = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(64)", maxLength: 64, nullable: true), + PhoneNumber = table.Column(type: "nvarchar(32)", maxLength: 32, nullable: true), + PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), + TwoFactorEnabled = table.Column(type: "bit", nullable: false), + LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), + LockoutEnabled = table.Column(type: "bit", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Post", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + UpdatedAt = table.Column(type: "datetime2", nullable: false), + UserId = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Title = table.Column(type: "nvarchar(160)", maxLength: 160, nullable: false), + Slug = table.Column(type: "nvarchar(160)", maxLength: 160, nullable: false), + Description = table.Column(type: "nvarchar(450)", maxLength: 450, nullable: false), + Content = table.Column(type: "nvarchar(max)", nullable: false), + Cover = table.Column(type: "nvarchar(160)", maxLength: 160, nullable: true), + Views = table.Column(type: "int", nullable: false), + PublishedAt = table.Column(type: "datetime2", nullable: true), + PostType = table.Column(type: "int", nullable: false), + State = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Post", x => x.Id); + table.ForeignKey( + name: "FK_Post_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Storages", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(128)", nullable: false), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + IsDeleted = table.Column(type: "bit", nullable: false), + DeletedAt = table.Column(type: "datetime2", nullable: true), + Slug = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), + Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: false), + Path = table.Column(type: "nvarchar(2048)", maxLength: 2048, nullable: false), + Length = table.Column(type: "bigint", nullable: false), + ContentType = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: false), + Type = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Storages", x => x.Id); + table.ForeignKey( + name: "FK_Storages_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserClaim", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + UserId = table.Column(type: "nvarchar(128)", nullable: false), + ClaimType = table.Column(type: "nvarchar(16)", maxLength: 16, nullable: true), + ClaimValue = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserClaim_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), + ProviderDisplayName = table.Column(type: "nvarchar(128)", maxLength: 128, nullable: true), + UserId = table.Column(type: "nvarchar(128)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogin_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(type: "nvarchar(128)", nullable: false), + LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(450)", nullable: false), + Value = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserToken_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Newsletters", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CreatedAt = table.Column(type: "datetime2", nullable: false, defaultValueSql: "getdate()"), + UpdatedAt = table.Column(type: "datetime2", nullable: false), + PostId = table.Column(type: "int", nullable: false), + Success = table.Column(type: "bit", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Newsletters", x => x.Id); + table.ForeignKey( + name: "FK_Newsletters_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PostCategories", + columns: table => new + { + PostId = table.Column(type: "int", nullable: false), + CategoryId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PostCategories", x => new { x.PostId, x.CategoryId }); + table.ForeignKey( + name: "FK_PostCategories_Categories_CategoryId", + column: x => x.CategoryId, + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PostCategories_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Newsletters_PostId", + table: "Newsletters", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_Options_Key", + table: "Options", + column: "Key", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_Slug", + table: "Post", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_UserId", + table: "Post", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_PostCategories_CategoryId", + table: "PostCategories", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Storages_UserId", + table: "Storages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true, + filter: "[NormalizedUserName] IS NOT NULL"); + + migrationBuilder.CreateIndex( + name: "IX_UserClaim_UserId", + table: "UserClaim", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogin_UserId", + table: "UserLogin", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Newsletters"); + + migrationBuilder.DropTable( + name: "Options"); + + migrationBuilder.DropTable( + name: "PostCategories"); + + migrationBuilder.DropTable( + name: "Storages"); + + migrationBuilder.DropTable( + name: "Subscribers"); + + migrationBuilder.DropTable( + name: "UserClaim"); + + migrationBuilder.DropTable( + name: "UserLogin"); + + migrationBuilder.DropTable( + name: "UserToken"); + + migrationBuilder.DropTable( + name: "Categories"); + + migrationBuilder.DropTable( + name: "Post"); + + migrationBuilder.DropTable( + name: "User"); + } + } +} diff --git a/src/Blogifier/Data/Migrations/SqlServer/SqlServerDbContextModelSnapshot.cs b/src/Blogifier/Data/Migrations/SqlServer/SqlServerDbContextModelSnapshot.cs new file mode 100644 index 000000000..3232e3c51 --- /dev/null +++ b/src/Blogifier/Data/Migrations/SqlServer/SqlServerDbContextModelSnapshot.cs @@ -0,0 +1,558 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Blogifier.Data.Migrations.SqlServer +{ + [DbContext(typeof(SqlServerDbContext))] + partial class SqlServerDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(0) + .HasDefaultValueSql("getdate()"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("bit"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("bit"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("bit"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("TwoFactorEnabled") + .HasColumnType("bit"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter("[NormalizedUserName] IS NOT NULL"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("Success") + .HasColumnType("bit"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("nvarchar(450)"); + + b.Property("PostType") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime2"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("nvarchar(160)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime2"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("int"); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("getdate()"); + + b.Property("DeletedAt") + .HasColumnType("datetime2"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderKey") + .HasColumnType("nvarchar(450)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("nvarchar(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("nvarchar(128)"); + + b.Property("LoginProvider") + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .HasColumnType("nvarchar(450)"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs b/src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.Designer.cs similarity index 89% rename from src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs rename to src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.Designer.cs index dd78f729d..97ac98e4c 100644 --- a/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.Designer.cs +++ b/src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.Designer.cs @@ -11,7 +11,7 @@ namespace Blogifier.Data.Migrations.Sqlite { [DbContext(typeof(SqliteDbContext))] - [Migration("20230608075855_Init")] + [Migration("20230608090804_Init")] partial class Init { /// @@ -103,7 +103,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT") .HasColumnOrder(1); @@ -141,7 +140,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.HasKey("Id"); @@ -180,7 +178,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.HasKey("Id"); @@ -205,7 +202,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.Property("Value") @@ -289,7 +285,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.Property("UserId") @@ -379,29 +374,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Storages"); }); - modelBuilder.Entity("Blogifier.Storages.StorageReference", b => - { - b.Property("StorageId") - .HasColumnType("INTEGER"); - - b.Property("EntityId") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasDefaultValueSql("datetime()"); - - b.HasKey("StorageId", "EntityId", "Type"); - - b.HasIndex("EntityId"); - - b.ToTable("StorageReferences", (string)null); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") @@ -522,25 +494,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("Blogifier.Storages.StorageReference", b => - { - b.HasOne("Blogifier.Shared.Post", "Post") - .WithMany("StorageReferences") - .HasForeignKey("EntityId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Blogifier.Storages.Storage", "Storage") - .WithMany("StorageReferences") - .HasForeignKey("StorageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Post"); - - b.Navigation("Storage"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Blogifier.Identity.UserInfo", null) @@ -576,13 +529,6 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Shared.Post", b => { b.Navigation("PostCategories"); - - b.Navigation("StorageReferences"); - }); - - modelBuilder.Entity("Blogifier.Storages.Storage", b => - { - b.Navigation("StorageReferences"); }); #pragma warning restore 612, 618 } diff --git a/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs b/src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.cs similarity index 91% rename from src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs rename to src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.cs index b5f9d20e8..57d66c929 100644 --- a/src/Blogifier/Data/Migrations/Sqlite/20230608075855_Init.cs +++ b/src/Blogifier/Data/Migrations/Sqlite/20230608090804_Init.cs @@ -258,32 +258,6 @@ protected override void Up(MigrationBuilder migrationBuilder) onDelete: ReferentialAction.Cascade); }); - migrationBuilder.CreateTable( - name: "StorageReferences", - columns: table => new - { - StorageId = table.Column(type: "INTEGER", nullable: false), - EntityId = table.Column(type: "INTEGER", nullable: false), - Type = table.Column(type: "INTEGER", nullable: false), - CreatedAt = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime()") - }, - constraints: table => - { - table.PrimaryKey("PK_StorageReferences", x => new { x.StorageId, x.EntityId, x.Type }); - table.ForeignKey( - name: "FK_StorageReferences_Post_EntityId", - column: x => x.EntityId, - principalTable: "Post", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_StorageReferences_Storages_StorageId", - column: x => x.StorageId, - principalTable: "Storages", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - migrationBuilder.CreateIndex( name: "IX_Newsletters_PostId", table: "Newsletters", @@ -311,11 +285,6 @@ protected override void Up(MigrationBuilder migrationBuilder) table: "PostCategories", column: "CategoryId"); - migrationBuilder.CreateIndex( - name: "IX_StorageReferences_EntityId", - table: "StorageReferences", - column: "EntityId"); - migrationBuilder.CreateIndex( name: "IX_Storages_UserId", table: "Storages", @@ -356,7 +325,7 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "PostCategories"); migrationBuilder.DropTable( - name: "StorageReferences"); + name: "Storages"); migrationBuilder.DropTable( name: "Subscribers"); @@ -376,9 +345,6 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "Post"); - migrationBuilder.DropTable( - name: "Storages"); - migrationBuilder.DropTable( name: "User"); } diff --git a/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs b/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs index 4d5476a47..7e1f4c644 100644 --- a/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs +++ b/src/Blogifier/Data/Migrations/Sqlite/SqliteDbContextModelSnapshot.cs @@ -100,7 +100,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT") .HasColumnOrder(1); @@ -138,7 +137,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.HasKey("Id"); @@ -177,7 +175,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.HasKey("Id"); @@ -202,7 +199,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.Property("Value") @@ -286,7 +282,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT"); b.Property("UpdatedAt") - .ValueGeneratedOnAddOrUpdate() .HasColumnType("TEXT"); b.Property("UserId") @@ -376,29 +371,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Storages"); }); - modelBuilder.Entity("Blogifier.Storages.StorageReference", b => - { - b.Property("StorageId") - .HasColumnType("INTEGER"); - - b.Property("EntityId") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("CreatedAt") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasDefaultValueSql("datetime()"); - - b.HasKey("StorageId", "EntityId", "Type"); - - b.HasIndex("EntityId"); - - b.ToTable("StorageReferences", (string)null); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") @@ -519,25 +491,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("Blogifier.Storages.StorageReference", b => - { - b.HasOne("Blogifier.Shared.Post", "Post") - .WithMany("StorageReferences") - .HasForeignKey("EntityId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Blogifier.Storages.Storage", "Storage") - .WithMany("StorageReferences") - .HasForeignKey("StorageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Post"); - - b.Navigation("Storage"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Blogifier.Identity.UserInfo", null) @@ -573,13 +526,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Blogifier.Shared.Post", b => { b.Navigation("PostCategories"); - - b.Navigation("StorageReferences"); - }); - - modelBuilder.Entity("Blogifier.Storages.Storage", b => - { - b.Navigation("StorageReferences"); }); #pragma warning restore 612, 618 } diff --git a/src/Blogifier/Data/SqlServerDbContext.cs b/src/Blogifier/Data/SqlServerDbContext.cs new file mode 100644 index 000000000..0f983483c --- /dev/null +++ b/src/Blogifier/Data/SqlServerDbContext.cs @@ -0,0 +1,75 @@ +using Blogifier.Data.ValueGeneration; +using Blogifier.Identity; +using Blogifier.Newsletters; +using Blogifier.Options; +using Blogifier.Shared; +using Blogifier.Storages; +using Microsoft.EntityFrameworkCore; + +namespace Blogifier.Data; + +public class SqlServerDbContext : AppDbContext +{ + public SqlServerDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + + // https://github.com/dotnet/EntityFramework.Docs/issues/3057 + // https://github.com/dotnet/efcore/issues/19765 + // TOTO No solution has been found + // This configuration is not updated when the entity is updated + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("getdate()"); + }); + + //modelBuilder.Entity(e => + //{ + // e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + //}); + } +} diff --git a/src/Blogifier/Data/SqliteDbContext.cs b/src/Blogifier/Data/SqliteDbContext.cs index 5b863f9ff..5c2c2365f 100644 --- a/src/Blogifier/Data/SqliteDbContext.cs +++ b/src/Blogifier/Data/SqliteDbContext.cs @@ -68,10 +68,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); }); - modelBuilder.Entity(e => - { - e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); - }); + //modelBuilder.Entity(e => + //{ + // e.Property(b => b.CreatedAt).HasDefaultValueSql("datetime()"); + //}); } } diff --git a/src/Blogifier/Posts/Post.cs b/src/Blogifier/Posts/Post.cs index 69692a055..2a5c2f658 100644 --- a/src/Blogifier/Posts/Post.cs +++ b/src/Blogifier/Posts/Post.cs @@ -31,5 +31,5 @@ public class Post : AppEntity public PostType PostType { get; set; } public PostState State { get; set; } public List? PostCategories { get; set; } - public List? StorageReferences { get; set; } + //public List? StorageReferences { get; set; } } diff --git a/src/Blogifier/Posts/PostProvider.cs b/src/Blogifier/Posts/PostProvider.cs index 9713c24d0..e99f6abce 100644 --- a/src/Blogifier/Posts/PostProvider.cs +++ b/src/Blogifier/Posts/PostProvider.cs @@ -102,7 +102,7 @@ public async Task GetEditorAsync(string slug) .AsNoTracking() .Include(m => m.PostCategories)! .ThenInclude(m => m.Category) - .Include(m => m.StorageReferences!.Where(s => s.Type == StorageReferenceType.Post)) + //.Include(m => m.StorageReferences!.Where(s => s.Type == StorageReferenceType.Post)) .AsSingleQuery() .Where(p => p.Slug == slug); return await _mapper.ProjectTo(query).FirstAsync(); diff --git a/src/Blogifier/Profiles/PostProfile.cs b/src/Blogifier/Profiles/PostProfile.cs index 58bac84da..85dd8b818 100644 --- a/src/Blogifier/Profiles/PostProfile.cs +++ b/src/Blogifier/Profiles/PostProfile.cs @@ -13,9 +13,10 @@ public PostProfile() CreateMap(); CreateMap() .ForMember(d => d.Categories, opt => opt.MapFrom(src => src.PostCategories)) - .ForMember(d => d.Storages, opt => opt.MapFrom(src => src.StorageReferences)) + //.ForMember(d => d.Storages, opt => opt.MapFrom(src => src.StorageReferences)) .ReverseMap() .ForMember(d => d.PostCategories, opt => opt.MapFrom(src => src.Categories)) - .ForMember(d => d.StorageReferences, opt => opt.MapFrom(src => src.Storages)); + //.ForMember(d => d.StorageReferences, opt => opt.MapFrom(src => src.Storages)) + ; } } diff --git a/src/Blogifier/Profiles/StorageProfile.cs b/src/Blogifier/Profiles/StorageProfile.cs index aded18903..51650d06e 100644 --- a/src/Blogifier/Profiles/StorageProfile.cs +++ b/src/Blogifier/Profiles/StorageProfile.cs @@ -9,8 +9,8 @@ public class StorageProfile : Profile public StorageProfile() { CreateMap().ReverseMap(); - CreateMap() - .IncludeMembers(m => m.Storage) - .ReverseMap(); + //CreateMap() + // .IncludeMembers(m => m.Storage) + // .ReverseMap(); } } diff --git a/src/Blogifier/Program.cs b/src/Blogifier/Program.cs index 01c786f4e..114ee0564 100644 --- a/src/Blogifier/Program.cs +++ b/src/Blogifier/Program.cs @@ -64,6 +64,10 @@ { builder.Services.AddDbContext(o => o.UseSqlite(connectionString)); } +else if ("SqlServer".Equals(provider, StringComparison.OrdinalIgnoreCase)) +{ + builder.Services.AddDbContext(o => o.UseSqlServer(connectionString)); +} else { throw new Exception($"Unsupported provider: {provider}"); diff --git a/src/Blogifier/Storages/Storage.cs b/src/Blogifier/Storages/Storage.cs index 9671c8017..2a2412d30 100644 --- a/src/Blogifier/Storages/Storage.cs +++ b/src/Blogifier/Storages/Storage.cs @@ -26,5 +26,5 @@ public class Storage [StringLength(128)] public string ContentType { get; set; } = default!; public StorageType Type { get; set; } - public List? StorageReferences { get; set; } + //public List? StorageReferences { get; set; } } diff --git a/src/Blogifier/Storages/StorageReference.cs b/src/Blogifier/Storages/StorageReference.cs index 78dc3415b..942b22813 100644 --- a/src/Blogifier/Storages/StorageReference.cs +++ b/src/Blogifier/Storages/StorageReference.cs @@ -1,15 +1,14 @@ using Blogifier.Shared; using System; -using System.ComponentModel.DataAnnotations.Schema; namespace Blogifier.Storages; -public class StorageReference -{ - public DateTime CreatedAt { get; set; } - public int StorageId { get; set; } - public Storage Storage { get; set; } = default!; - public int EntityId { get; set; } - public StorageReferenceType Type { get; set; } - public Post? Post { get; set; } -} +//public class StorageReference +//{ +// public DateTime CreatedAt { get; set; } +// public int StorageId { get; set; } +// public Storage Storage { get; set; } = default!; +// public int EntityId { get; set; } +// public StorageReferenceType Type { get; set; } +// public Post? Post { get; set; } +//} diff --git a/src/Blogifier/appsettings.json b/src/Blogifier/appsettings.json index 6428eb5c2..39348e465 100644 --- a/src/Blogifier/appsettings.json +++ b/src/Blogifier/appsettings.json @@ -1,8 +1,8 @@ { "Blogifier": { - "DbProvider": "MySql", - "ConnString": "server=mysql;user=root;password=root;database=blogifier;", + "DbProvider": "Sqlite", + "ConnString": "Data Source=App_Data/blogifier.db", //"Redis": "redis:6379,password=root,defaultDatabase=0", "Salt": "SECRET-CHANGE-ME!", "DemoMode": false, From 404034b41eaffc68724b004bae9165cee8fb0c57 Mon Sep 17 00:00:00 2001 From: dorthl Date: Thu, 8 Jun 2023 17:35:00 +0800 Subject: [PATCH 3/5] realize MySql provider --- docs/02-Database.md | 1 + .../MySql/20230608093107_Init.Designer.cs | 536 ++++++++++++++++++ .../Migrations/MySql/20230608093107_Init.cs | 422 ++++++++++++++ .../MySql/MySqlDbContextModelSnapshot.cs | 533 +++++++++++++++++ src/Blogifier/Data/MySqlDbContext.cs | 65 +++ src/Blogifier/Program.cs | 5 + src/Blogifier/Storages/StorageReference.cs | 8 +- 7 files changed, 1569 insertions(+), 1 deletion(-) create mode 100644 src/Blogifier/Data/Migrations/MySql/20230608093107_Init.Designer.cs create mode 100644 src/Blogifier/Data/Migrations/MySql/20230608093107_Init.cs create mode 100644 src/Blogifier/Data/Migrations/MySql/MySqlDbContextModelSnapshot.cs create mode 100644 src/Blogifier/Data/MySqlDbContext.cs diff --git a/docs/02-Database.md b/docs/02-Database.md index 2cc6f5f73..3b9e2b8b0 100644 --- a/docs/02-Database.md +++ b/docs/02-Database.md @@ -25,6 +25,7 @@ dotnet ef migrations remove dotnet ef migrations add Init --context SqliteDbContext --output-dir Data/Migrations/Sqlite dotnet ef migrations add Init --context SqlServerDbContext --output-dir Data/Migrations/SqlServer +dotnet ef migrations add Init --context MySqlDbContext --output-dir Data/Migrations/MySql ``` First command should re-generate provider specific code migrations and second will diff --git a/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.Designer.cs b/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.Designer.cs new file mode 100644 index 000000000..2bd7fc94b --- /dev/null +++ b/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.Designer.cs @@ -0,0 +1,536 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Blogifier.Data.Migrations.MySql +{ + [DbContext(typeof(MySqlDbContext))] + [Migration("20230608093107_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnOrder(0); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("Success") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("varchar(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("varchar(450)"); + + b.Property("PostType") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime(6)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("int"); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("varchar(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(128)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.cs b/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.cs new file mode 100644 index 000000000..445fc0467 --- /dev/null +++ b/src/Blogifier/Data/Migrations/MySql/20230608093107_Init.cs @@ -0,0 +1,422 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Blogifier.Data.Migrations.MySql +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Categories", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Content = table.Column(type: "varchar(120)", maxLength: 120, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(255)", maxLength: 255, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Categories", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Options", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), + Key = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Options", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Subscribers", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), + Email = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Ip = table.Column(type: "varchar(80)", maxLength: 80, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Country = table.Column(type: "varchar(120)", maxLength: 120, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Region = table.Column(type: "varchar(120)", maxLength: 120, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Subscribers", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), + Id = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + NickName = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Avatar = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Bio = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Gender = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Type = table.Column(type: "int", nullable: false), + State = table.Column(type: "int", nullable: false), + UserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedUserName = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Email = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + NormalizedEmail = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + EmailConfirmed = table.Column(type: "tinyint(1)", nullable: false), + PasswordHash = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + SecurityStamp = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(64)", maxLength: 64, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PhoneNumber = table.Column(type: "varchar(32)", maxLength: 32, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + PhoneNumberConfirmed = table.Column(type: "tinyint(1)", nullable: false), + TwoFactorEnabled = table.Column(type: "tinyint(1)", nullable: false), + LockoutEnd = table.Column(type: "datetime(6)", nullable: true), + LockoutEnabled = table.Column(type: "tinyint(1)", nullable: false), + AccessFailedCount = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Post", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), + UserId = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Title = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Slug = table.Column(type: "varchar(160)", maxLength: 160, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "varchar(450)", maxLength: 450, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Content = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Cover = table.Column(type: "varchar(160)", maxLength: 160, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Views = table.Column(type: "int", nullable: false), + PublishedAt = table.Column(type: "datetime(6)", nullable: true), + PostType = table.Column(type: "int", nullable: false), + State = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Post", x => x.Id); + table.ForeignKey( + name: "FK_Post_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Storages", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "varchar(128)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false), + DeletedAt = table.Column(type: "datetime(6)", nullable: true), + Slug = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(256)", maxLength: 256, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Path = table.Column(type: "varchar(2048)", maxLength: 2048, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Length = table.Column(type: "bigint", nullable: false), + ContentType = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Type = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Storages", x => x.Id); + table.ForeignKey( + name: "FK_Storages_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "UserClaim", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UserId = table.Column(type: "varchar(128)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimType = table.Column(type: "varchar(16)", maxLength: 16, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClaimValue = table.Column(type: "varchar(256)", maxLength: 256, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserClaim_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderKey = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + ProviderDisplayName = table.Column(type: "varchar(128)", maxLength: 128, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + UserId = table.Column(type: "varchar(128)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogin_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(type: "varchar(128)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + LoginProvider = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Name = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "varchar(1024)", maxLength: 1024, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserToken_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Newsletters", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + UpdatedAt = table.Column(type: "datetime(6)", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.ComputedColumn), + PostId = table.Column(type: "int", nullable: false), + Success = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Newsletters", x => x.Id); + table.ForeignKey( + name: "FK_Newsletters_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "PostCategories", + columns: table => new + { + PostId = table.Column(type: "int", nullable: false), + CategoryId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PostCategories", x => new { x.PostId, x.CategoryId }); + table.ForeignKey( + name: "FK_PostCategories_Categories_CategoryId", + column: x => x.CategoryId, + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PostCategories_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Newsletters_PostId", + table: "Newsletters", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_Options_Key", + table: "Options", + column: "Key", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_Slug", + table: "Post", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_UserId", + table: "Post", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_PostCategories_CategoryId", + table: "PostCategories", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Storages_UserId", + table: "Storages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserClaim_UserId", + table: "UserClaim", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogin_UserId", + table: "UserLogin", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Newsletters"); + + migrationBuilder.DropTable( + name: "Options"); + + migrationBuilder.DropTable( + name: "PostCategories"); + + migrationBuilder.DropTable( + name: "Storages"); + + migrationBuilder.DropTable( + name: "Subscribers"); + + migrationBuilder.DropTable( + name: "UserClaim"); + + migrationBuilder.DropTable( + name: "UserLogin"); + + migrationBuilder.DropTable( + name: "UserToken"); + + migrationBuilder.DropTable( + name: "Categories"); + + migrationBuilder.DropTable( + name: "Post"); + + migrationBuilder.DropTable( + name: "User"); + } + } +} diff --git a/src/Blogifier/Data/Migrations/MySql/MySqlDbContextModelSnapshot.cs b/src/Blogifier/Data/Migrations/MySql/MySqlDbContextModelSnapshot.cs new file mode 100644 index 000000000..68b4308e9 --- /dev/null +++ b/src/Blogifier/Data/Migrations/MySql/MySqlDbContextModelSnapshot.cs @@ -0,0 +1,533 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Blogifier.Data.Migrations.MySql +{ + [DbContext(typeof(MySqlDbContext))] + partial class MySqlDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("int"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)") + .HasColumnOrder(0); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("LockoutEnd") + .HasColumnType("datetime(6)"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("tinyint(1)"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("TwoFactorEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("PostId") + .HasColumnType("int"); + + b.Property("Success") + .HasColumnType("tinyint(1)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("varchar(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("varchar(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("varchar(450)"); + + b.Property("PostType") + .HasColumnType("int"); + + b.Property("PublishedAt") + .HasColumnType("datetime(6)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("State") + .HasColumnType("int"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("varchar(160)"); + + b.Property("UpdatedAt") + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Views") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("int"); + + b.Property("CategoryId") + .HasColumnType("int"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("datetime(6)"); + + b.Property("DeletedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("varchar(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("ProviderKey") + .HasColumnType("varchar(255)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("varchar(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("varchar(128)"); + + b.Property("LoginProvider") + .HasColumnType("varchar(255)"); + + b.Property("Name") + .HasColumnType("varchar(255)"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/MySqlDbContext.cs b/src/Blogifier/Data/MySqlDbContext.cs new file mode 100644 index 000000000..380ea230f --- /dev/null +++ b/src/Blogifier/Data/MySqlDbContext.cs @@ -0,0 +1,65 @@ +using Blogifier.Identity; +using Blogifier.Newsletters; +using Blogifier.Options; +using Blogifier.Shared; +using Blogifier.Storages; +using Microsoft.EntityFrameworkCore; + +namespace Blogifier.Data; + +public class MySqlDbContext : AppDbContext +{ + public MySqlDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + e.Property(b => b.UpdatedAt).ValueGeneratedOnAddOrUpdate(); + }); + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + e.Property(b => b.UpdatedAt).ValueGeneratedOnAddOrUpdate(); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + e.Property(b => b.UpdatedAt).ValueGeneratedOnAddOrUpdate(); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + e.Property(b => b.UpdatedAt).ValueGeneratedOnAddOrUpdate(); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + e.Property(b => b.UpdatedAt).ValueGeneratedOnAddOrUpdate(); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + }); + + //modelBuilder.Entity(e => + //{ + // e.Property(b => b.CreatedAt).ValueGeneratedOnAdd(); + //}); + } +} diff --git a/src/Blogifier/Program.cs b/src/Blogifier/Program.cs index 114ee0564..9a98f62dc 100644 --- a/src/Blogifier/Program.cs +++ b/src/Blogifier/Program.cs @@ -68,6 +68,11 @@ { builder.Services.AddDbContext(o => o.UseSqlServer(connectionString)); } +else if ("MySql".Equals(provider, StringComparison.OrdinalIgnoreCase)) +{ + var version = ServerVersion.AutoDetect(connectionString); + builder.Services.AddDbContext(o => o.UseMySql(connectionString, version)); +} else { throw new Exception($"Unsupported provider: {provider}"); diff --git a/src/Blogifier/Storages/StorageReference.cs b/src/Blogifier/Storages/StorageReference.cs index 942b22813..8a02d0dcd 100644 --- a/src/Blogifier/Storages/StorageReference.cs +++ b/src/Blogifier/Storages/StorageReference.cs @@ -1,8 +1,14 @@ using Blogifier.Shared; +using Microsoft.Identity.Client.Extensions.Msal; using System; - namespace Blogifier.Storages; + +// TOTO In the sql server implementation, +// it is found that there may be problems in the design of StorageReference table, +// and the storage reference function is not implemented for the time being, so it is commented out + + //public class StorageReference //{ // public DateTime CreatedAt { get; set; } From af95902f559c9e59c412ea8cffaf98cac07230bf Mon Sep 17 00:00:00 2001 From: dorthl Date: Thu, 8 Jun 2023 17:57:29 +0800 Subject: [PATCH 4/5] realize Postgres provider --- docs/02-Database.md | 1 + .../Postgres/20230608094908_Init.Designer.cs | 555 ++++++++++++++++++ .../Postgres/20230608094908_Init.cs | 353 +++++++++++ .../PostgresDbContextModelSnapshot.cs | 552 +++++++++++++++++ src/Blogifier/Data/PostgresDbContext.cs | 76 +++ src/Blogifier/Posts/ImportManager.cs | 3 +- src/Blogifier/Program.cs | 4 + 7 files changed, 1543 insertions(+), 1 deletion(-) create mode 100644 src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.Designer.cs create mode 100644 src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.cs create mode 100644 src/Blogifier/Data/Migrations/Postgres/PostgresDbContextModelSnapshot.cs create mode 100644 src/Blogifier/Data/PostgresDbContext.cs diff --git a/docs/02-Database.md b/docs/02-Database.md index 3b9e2b8b0..7a671f51f 100644 --- a/docs/02-Database.md +++ b/docs/02-Database.md @@ -26,6 +26,7 @@ dotnet ef migrations remove dotnet ef migrations add Init --context SqliteDbContext --output-dir Data/Migrations/Sqlite dotnet ef migrations add Init --context SqlServerDbContext --output-dir Data/Migrations/SqlServer dotnet ef migrations add Init --context MySqlDbContext --output-dir Data/Migrations/MySql +dotnet ef migrations add Init --context PostgresDbContext --output-dir Data/Migrations/Postgres ``` First command should re-generate provider specific code migrations and second will diff --git a/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.Designer.cs b/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.Designer.cs new file mode 100644 index 000000000..f3a45afcd --- /dev/null +++ b/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.Designer.cs @@ -0,0 +1,555 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Blogifier.Data.Migrations.Postgres +{ + [DbContext(typeof(PostgresDbContext))] + [Migration("20230608094908_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnOrder(0) + .HasDefaultValueSql("now()"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("PostId") + .HasColumnType("integer"); + + b.Property("Success") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("character varying(450)"); + + b.Property("PostType") + .HasColumnType("integer"); + + b.Property("PublishedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Views") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("character varying(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("character varying(128)"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.cs b/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.cs new file mode 100644 index 000000000..42ac2abb5 --- /dev/null +++ b/src/Blogifier/Data/Migrations/Postgres/20230608094908_Init.cs @@ -0,0 +1,353 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Blogifier.Data.Migrations.Postgres +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Categories", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + Content = table.Column(type: "character varying(120)", maxLength: 120, nullable: false), + Description = table.Column(type: "character varying(255)", maxLength: 255, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Categories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Options", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Key = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Value = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Options", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Subscribers", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Email = table.Column(type: "character varying(160)", maxLength: 160, nullable: false), + Ip = table.Column(type: "character varying(80)", maxLength: 80, nullable: true), + Country = table.Column(type: "character varying(120)", maxLength: 120, nullable: true), + Region = table.Column(type: "character varying(120)", maxLength: 120, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Subscribers", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "User", + columns: table => new + { + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + Id = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + NickName = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Avatar = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true), + Bio = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: true), + Gender = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + Type = table.Column(type: "integer", nullable: false), + State = table.Column(type: "integer", nullable: false), + UserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + NormalizedUserName = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + Email = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + NormalizedEmail = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + EmailConfirmed = table.Column(type: "boolean", nullable: false), + PasswordHash = table.Column(type: "character varying(256)", maxLength: 256, nullable: true), + SecurityStamp = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + ConcurrencyStamp = table.Column(type: "character varying(64)", maxLength: 64, nullable: true), + PhoneNumber = table.Column(type: "character varying(32)", maxLength: 32, nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false), + AccessFailedCount = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_User", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Post", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UserId = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Title = table.Column(type: "character varying(160)", maxLength: 160, nullable: false), + Slug = table.Column(type: "character varying(160)", maxLength: 160, nullable: false), + Description = table.Column(type: "character varying(450)", maxLength: 450, nullable: false), + Content = table.Column(type: "text", nullable: false), + Cover = table.Column(type: "character varying(160)", maxLength: 160, nullable: true), + Views = table.Column(type: "integer", nullable: false), + PublishedAt = table.Column(type: "timestamp with time zone", nullable: true), + PostType = table.Column(type: "integer", nullable: false), + State = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Post", x => x.Id); + table.ForeignKey( + name: "FK_Post_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Storages", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "character varying(128)", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + IsDeleted = table.Column(type: "boolean", nullable: false), + DeletedAt = table.Column(type: "timestamp with time zone", nullable: true), + Slug = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + Name = table.Column(type: "character varying(256)", maxLength: 256, nullable: false), + Path = table.Column(type: "character varying(2048)", maxLength: 2048, nullable: false), + Length = table.Column(type: "bigint", nullable: false), + ContentType = table.Column(type: "character varying(128)", maxLength: 128, nullable: false), + Type = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Storages", x => x.Id); + table.ForeignKey( + name: "FK_Storages_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserClaim", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "character varying(128)", nullable: false), + ClaimType = table.Column(type: "character varying(16)", maxLength: 16, nullable: true), + ClaimValue = table.Column(type: "character varying(256)", maxLength: 256, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaim", x => x.Id); + table.ForeignKey( + name: "FK_UserClaim_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogin", + columns: table => new + { + LoginProvider = table.Column(type: "text", nullable: false), + ProviderKey = table.Column(type: "text", nullable: false), + ProviderDisplayName = table.Column(type: "character varying(128)", maxLength: 128, nullable: true), + UserId = table.Column(type: "character varying(128)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogin", x => new { x.LoginProvider, x.ProviderKey }); + table.ForeignKey( + name: "FK_UserLogin_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserToken", + columns: table => new + { + UserId = table.Column(type: "character varying(128)", nullable: false), + LoginProvider = table.Column(type: "text", nullable: false), + Name = table.Column(type: "text", nullable: false), + Value = table.Column(type: "character varying(1024)", maxLength: 1024, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserToken", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_UserToken_User_UserId", + column: x => x.UserId, + principalTable: "User", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Newsletters", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false), + PostId = table.Column(type: "integer", nullable: false), + Success = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Newsletters", x => x.Id); + table.ForeignKey( + name: "FK_Newsletters_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PostCategories", + columns: table => new + { + PostId = table.Column(type: "integer", nullable: false), + CategoryId = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PostCategories", x => new { x.PostId, x.CategoryId }); + table.ForeignKey( + name: "FK_PostCategories_Categories_CategoryId", + column: x => x.CategoryId, + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PostCategories_Post_PostId", + column: x => x.PostId, + principalTable: "Post", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Newsletters_PostId", + table: "Newsletters", + column: "PostId"); + + migrationBuilder.CreateIndex( + name: "IX_Options_Key", + table: "Options", + column: "Key", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_Slug", + table: "Post", + column: "Slug", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Post_UserId", + table: "Post", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_PostCategories_CategoryId", + table: "PostCategories", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Storages_UserId", + table: "Storages", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "EmailIndex", + table: "User", + column: "NormalizedEmail"); + + migrationBuilder.CreateIndex( + name: "UserNameIndex", + table: "User", + column: "NormalizedUserName", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_UserClaim_UserId", + table: "UserClaim", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogin_UserId", + table: "UserLogin", + column: "UserId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Newsletters"); + + migrationBuilder.DropTable( + name: "Options"); + + migrationBuilder.DropTable( + name: "PostCategories"); + + migrationBuilder.DropTable( + name: "Storages"); + + migrationBuilder.DropTable( + name: "Subscribers"); + + migrationBuilder.DropTable( + name: "UserClaim"); + + migrationBuilder.DropTable( + name: "UserLogin"); + + migrationBuilder.DropTable( + name: "UserToken"); + + migrationBuilder.DropTable( + name: "Categories"); + + migrationBuilder.DropTable( + name: "Post"); + + migrationBuilder.DropTable( + name: "User"); + } + } +} diff --git a/src/Blogifier/Data/Migrations/Postgres/PostgresDbContextModelSnapshot.cs b/src/Blogifier/Data/Migrations/Postgres/PostgresDbContextModelSnapshot.cs new file mode 100644 index 000000000..324b7c149 --- /dev/null +++ b/src/Blogifier/Data/Migrations/Postgres/PostgresDbContextModelSnapshot.cs @@ -0,0 +1,552 @@ +// +using System; +using Blogifier.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Blogifier.Data.Migrations.Postgres +{ + [DbContext(typeof(PostgresDbContext))] + partial class PostgresDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Blogifier.Identity.UserInfo", b => + { + b.Property("Id") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("Avatar") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Bio") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasColumnOrder(0) + .HasDefaultValueSql("now()"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("Gender") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NickName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PhoneNumber") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnOrder(1); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("PostId") + .HasColumnType("integer"); + + b.Property("Success") + .HasColumnType("boolean"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("PostId"); + + b.ToTable("Newsletters"); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Subscriber", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Country") + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("Ip") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("Region") + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Subscribers"); + }); + + modelBuilder.Entity("Blogifier.Options.OptionInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("Options", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.HasKey("Id"); + + b.ToTable("Categories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("Cover") + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(450) + .HasColumnType("character varying(450)"); + + b.Property("PostType") + .HasColumnType("integer"); + + b.Property("PublishedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("State") + .HasColumnType("integer"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(160) + .HasColumnType("character varying(160)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Views") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Slug") + .IsUnique(); + + b.HasIndex("UserId"); + + b.ToTable("Post", (string)null); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.Property("PostId") + .HasColumnType("integer"); + + b.Property("CategoryId") + .HasColumnType("integer"); + + b.HasKey("PostId", "CategoryId"); + + b.HasIndex("CategoryId"); + + b.ToTable("PostCategories", (string)null); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("now()"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("Length") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Path") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Slug") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Storages"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasMaxLength(16) + .HasColumnType("character varying(16)"); + + b.Property("ClaimValue") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaim", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("UserId") + .IsRequired() + .HasColumnType("character varying(128)"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogin", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("character varying(128)"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("UserToken", (string)null); + }); + + modelBuilder.Entity("Blogifier.Newsletters.Newsletter", b => + { + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany() + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Blogifier.Shared.PostCategory", b => + { + b.HasOne("Blogifier.Shared.Category", "Category") + .WithMany("PostCategories") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Blogifier.Shared.Post", "Post") + .WithMany("PostCategories") + .HasForeignKey("PostId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Category"); + + b.Navigation("Post"); + }); + + modelBuilder.Entity("Blogifier.Storages.Storage", b => + { + b.HasOne("Blogifier.Identity.UserInfo", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Blogifier.Identity.UserInfo", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Blogifier.Shared.Category", b => + { + b.Navigation("PostCategories"); + }); + + modelBuilder.Entity("Blogifier.Shared.Post", b => + { + b.Navigation("PostCategories"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Blogifier/Data/PostgresDbContext.cs b/src/Blogifier/Data/PostgresDbContext.cs new file mode 100644 index 000000000..5cc287860 --- /dev/null +++ b/src/Blogifier/Data/PostgresDbContext.cs @@ -0,0 +1,76 @@ +using Blogifier.Data.ValueGeneration; +using Blogifier.Identity; +using Blogifier.Newsletters; +using Blogifier.Options; +using Blogifier.Shared; +using Blogifier.Storages; +using Microsoft.EntityFrameworkCore; + +namespace Blogifier.Data; + +public class PostgresDbContext : AppDbContext +{ + public PostgresDbContext(DbContextOptions options) : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + + // https://github.com/dotnet/EntityFramework.Docs/issues/3057 + // https://github.com/dotnet/efcore/issues/19765 + // TOTO No solution has been found + // This configuration is not updated when the entity is updated + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + e.Property(b => b.UpdatedAt) + .HasValueGenerator(typeof(DateTimetValueGenerator)); + }); + + modelBuilder.Entity(e => + { + e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + }); + + //modelBuilder.Entity(e => + //{ + // e.Property(b => b.CreatedAt).HasDefaultValueSql("now()"); + //}); + } +} diff --git a/src/Blogifier/Posts/ImportManager.cs b/src/Blogifier/Posts/ImportManager.cs index 19c6c5c26..18a13a82d 100644 --- a/src/Blogifier/Posts/ImportManager.cs +++ b/src/Blogifier/Posts/ImportManager.cs @@ -49,7 +49,7 @@ public async Task> WriteAsync(ImportDto request, stri continue; } - var publishedAt = post.PublishedAt!.Value; + var publishedAt = post.PublishedAt!.Value.ToUniversalTime(); if (post.Cover != null && !post.Cover.Equals(BlogifierConstant.DefaultCover, StringComparison.Ordinal)) { @@ -66,6 +66,7 @@ public async Task> WriteAsync(ImportDto request, stri post.Description = markdownDescription; post.State = PostState.Release; + post.PublishedAt = publishedAt; posts.Add(post); } diff --git a/src/Blogifier/Program.cs b/src/Blogifier/Program.cs index 9a98f62dc..35216ac2a 100644 --- a/src/Blogifier/Program.cs +++ b/src/Blogifier/Program.cs @@ -73,6 +73,10 @@ var version = ServerVersion.AutoDetect(connectionString); builder.Services.AddDbContext(o => o.UseMySql(connectionString, version)); } +else if ("Postgres".Equals(provider, StringComparison.OrdinalIgnoreCase)) +{ + builder.Services.AddDbContext(o => o.UseNpgsql(connectionString)); +} else { throw new Exception($"Unsupported provider: {provider}"); From ccec455ba3fd566f3529eca714c90242587f2f07 Mon Sep 17 00:00:00 2001 From: dorthl Date: Thu, 8 Jun 2023 18:33:52 +0800 Subject: [PATCH 5/5] edit document --- docs/02-Database.md | 73 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/docs/02-Database.md b/docs/02-Database.md index 7a671f51f..e7c5ede61 100644 --- a/docs/02-Database.md +++ b/docs/02-Database.md @@ -1,33 +1,74 @@ -### To change Database Provider - -1. Update provider and connection string in the `appsettings.json`: +## To change Database Provider +Update provider and connection string in the `appsettings.json`: +#### SQLite +``` json +"Blogifier": { + "DbProvider": "Sqlite", + "ConnString": "Data Source=App_Data/blogifier.db", + ... +} ``` +It is recommended to put the database file under the App_Data folder. The logs and local pictures in the project will be stored in this path for persistence. + +#### SqlServer +``` json "Blogifier": { - "DbProvider": "SQLite", - "ConnString": "Data Source=Blog.db", + "DbProvider": "SqlServer", + "ConnString": "Data Source=mssql; User Id=sa; Password=Password; Initial Catalog=blogifier;TrustServerCertificate=True", ... } ``` -Valid providers: `Sqlite`, `SqlServer`, `Postgres`, `MySql` (you'll need to supply valid connection string) +In the latest version of sql server connection, SqlClient will perform a secure connection by default, and you need to add a server certificate to the system. The example adds TrustServerCertificate=True to ignore this requirement. You can also delete this ignore and enable a secure connection. -2. Remove `Blogifier/Data/Migrations` folder with existing migrations -3. In the Visual Studio, open `Package Manager Console`, set `Blogifier` -as Default project and run these commands: +#### MySql +``` json +"Blogifier": { + "DbProvider": "MySql", + "ConnString": "server=mysql;user=root;password=password;database=blogifier", + ... +} +``` +#### Postgres +``` json +"Blogifier": { + "DbProvider": "Postgres", + "ConnString": "Host=postgres;Username=postgres;Password=password;Database=blogifier;", + ... +} ``` -Add-Migration Init -o Data\Migrations -Update-Database +In the above example, ConnString requires you to fill in the correct database host address username and password to connect normally + + +## When a change to an entity field requires a database migration + +The database migration is stored in the src/Blogifier/Data/Migrations directory. The current project is still under development. When there is a modification, this directory may be deleted for quick migration. After the project is officially released, it is no longer recommended to delete the updated database migrate. -# cil -dotnet ef migrations Init -o Data\Migrations -dotnet ef migrations remove +The following is the way to generate a new migration or delete the previous migration command. Before executing the command, please configure the corresponding DbProvider and ConnString in appsettings.json and then execute the corresponding migration command +``` shell +# Revert Migration Tool +dotnet tool restore +# Jump to project directory +cd src/Blogifier + +# Sqlite dotnet ef migrations add Init --context SqliteDbContext --output-dir Data/Migrations/Sqlite +dotnet ef migrations remove --context SqliteDbContext + +# SqlServer dotnet ef migrations add Init --context SqlServerDbContext --output-dir Data/Migrations/SqlServer +dotnet ef migrations remove --context SqlServerDbContext + +# MySql dotnet ef migrations add Init --context MySqlDbContext --output-dir Data/Migrations/MySql +dotnet ef migrations remove --context MySqlDbContext + +# Postgres dotnet ef migrations add Init --context PostgresDbContext --output-dir Data/Migrations/Postgres +dotnet ef migrations remove --context MySqlDbContext ``` -First command should re-generate provider specific code migrations and second will -execute them and create database specified in the connection string. +### Warn +Do not add or delete database migration at will. After the application generates data, random migration may cause data loss. This project will automatically apply the migration when it starts.