From 824da227f6a18c9aa265e5a7b16557b5e22f485f Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 29 Feb 2020 19:32:58 +0800 Subject: Now posts use local id in same timeline. Also fixed some unconforming place in migrations. --- Timeline/Entities/TimelineEntity.cs | 3 + Timeline/Entities/TimelinePostEntity.cs | 3 + .../20200105150407_Initialize.Designer.cs | 9 +- .../20200131100517_RefactorUser.Designer.cs | 9 +- .../20200221064341_AddJwtToken.Designer.cs | 13 +- .../20200229103848_AddPostLocalId.Designer.cs | 265 +++++++++++++++++++++ .../Migrations/20200229103848_AddPostLocalId.cs | 42 ++++ .../Migrations/DatabaseContextModelSnapshot.cs | 12 +- Timeline/Services/TimelineService.cs | 15 +- 9 files changed, 344 insertions(+), 27 deletions(-) create mode 100644 Timeline/Migrations/20200229103848_AddPostLocalId.Designer.cs create mode 100644 Timeline/Migrations/20200229103848_AddPostLocalId.cs (limited to 'Timeline') diff --git a/Timeline/Entities/TimelineEntity.cs b/Timeline/Entities/TimelineEntity.cs index 0b252bab..56b36d4e 100644 --- a/Timeline/Entities/TimelineEntity.cs +++ b/Timeline/Entities/TimelineEntity.cs @@ -35,6 +35,9 @@ namespace Timeline.Entities [Column("create_time")] public DateTime CreateTime { get; set; } + [Column("current_post_local_id")] + public long CurrentPostLocalId { get; set; } + public List Members { get; set; } = default!; public List Posts { get; set; } = default!; diff --git a/Timeline/Entities/TimelinePostEntity.cs b/Timeline/Entities/TimelinePostEntity.cs index a615c61f..5805abe0 100644 --- a/Timeline/Entities/TimelinePostEntity.cs +++ b/Timeline/Entities/TimelinePostEntity.cs @@ -10,6 +10,9 @@ namespace Timeline.Entities [Column("id"), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { get; set; } + [Column("local_id")] + public long LocalId { get; set; } + [Column("timeline")] public long TimelineId { get; set; } diff --git a/Timeline/Migrations/20200105150407_Initialize.Designer.cs b/Timeline/Migrations/20200105150407_Initialize.Designer.cs index ca93fcb3..99e4eaac 100644 --- a/Timeline/Migrations/20200105150407_Initialize.Designer.cs +++ b/Timeline/Migrations/20200105150407_Initialize.Designer.cs @@ -127,8 +127,7 @@ namespace Timeline.Migrations b.Property("Name") .IsRequired() .HasColumnName("name") - .HasColumnType("TEXT") - .HasMaxLength(26); + .HasColumnType("TEXT"); b.Property("RoleString") .IsRequired() @@ -162,8 +161,7 @@ namespace Timeline.Migrations b.Property("ETag") .HasColumnName("etag") - .HasColumnType("TEXT") - .HasMaxLength(30); + .HasColumnType("TEXT"); b.Property("LastModified") .HasColumnName("last_modified") @@ -193,8 +191,7 @@ namespace Timeline.Migrations b.Property("Nickname") .HasColumnName("nickname") - .HasColumnType("TEXT") - .HasMaxLength(26); + .HasColumnType("TEXT"); b.Property("UserId") .HasColumnType("INTEGER"); diff --git a/Timeline/Migrations/20200131100517_RefactorUser.Designer.cs b/Timeline/Migrations/20200131100517_RefactorUser.Designer.cs index fb5e8a30..9b78eb15 100644 --- a/Timeline/Migrations/20200131100517_RefactorUser.Designer.cs +++ b/Timeline/Migrations/20200131100517_RefactorUser.Designer.cs @@ -125,8 +125,7 @@ namespace Timeline.Migrations b.Property("ETag") .HasColumnName("etag") - .HasColumnType("TEXT") - .HasMaxLength(30); + .HasColumnType("TEXT"); b.Property("LastModified") .HasColumnName("last_modified") @@ -157,8 +156,7 @@ namespace Timeline.Migrations b.Property("Nickname") .HasColumnName("nickname") - .HasColumnType("TEXT") - .HasMaxLength(100); + .HasColumnType("TEXT"); b.Property("Password") .IsRequired() @@ -173,8 +171,7 @@ namespace Timeline.Migrations b.Property("Username") .IsRequired() .HasColumnName("username") - .HasColumnType("TEXT") - .HasMaxLength(26); + .HasColumnType("TEXT"); b.Property("Version") .ValueGeneratedOnAdd() diff --git a/Timeline/Migrations/20200221064341_AddJwtToken.Designer.cs b/Timeline/Migrations/20200221064341_AddJwtToken.Designer.cs index 56596249..eb328b52 100644 --- a/Timeline/Migrations/20200221064341_AddJwtToken.Designer.cs +++ b/Timeline/Migrations/20200221064341_AddJwtToken.Designer.cs @@ -25,9 +25,9 @@ namespace Timeline.Migrations .HasColumnName("id") .HasColumnType("INTEGER"); - b.Property("Token") + b.Property("Key") .IsRequired() - .HasColumnName("token") + .HasColumnName("key") .HasColumnType("BLOB"); b.HasKey("Id"); @@ -142,8 +142,7 @@ namespace Timeline.Migrations b.Property("ETag") .HasColumnName("etag") - .HasColumnType("TEXT") - .HasMaxLength(30); + .HasColumnType("TEXT"); b.Property("LastModified") .HasColumnName("last_modified") @@ -174,8 +173,7 @@ namespace Timeline.Migrations b.Property("Nickname") .HasColumnName("nickname") - .HasColumnType("TEXT") - .HasMaxLength(100); + .HasColumnType("TEXT"); b.Property("Password") .IsRequired() @@ -190,8 +188,7 @@ namespace Timeline.Migrations b.Property("Username") .IsRequired() .HasColumnName("username") - .HasColumnType("TEXT") - .HasMaxLength(26); + .HasColumnType("TEXT"); b.Property("Version") .ValueGeneratedOnAdd() diff --git a/Timeline/Migrations/20200229103848_AddPostLocalId.Designer.cs b/Timeline/Migrations/20200229103848_AddPostLocalId.Designer.cs new file mode 100644 index 00000000..cf6ae8a3 --- /dev/null +++ b/Timeline/Migrations/20200229103848_AddPostLocalId.Designer.cs @@ -0,0 +1,265 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Timeline.Entities; + +namespace Timeline.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20200229103848_AddPostLocalId")] + partial class AddPostLocalId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.2"); + + modelBuilder.Entity("Timeline.Entities.JwtTokenEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("Key") + .IsRequired() + .HasColumnName("key") + .HasColumnType("BLOB"); + + b.HasKey("Id"); + + b.ToTable("jwt_token"); + }); + + modelBuilder.Entity("Timeline.Entities.TimelineEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("CreateTime") + .HasColumnName("create_time") + .HasColumnType("TEXT"); + + b.Property("CurrentPostLocalId") + .HasColumnName("current_post_local_id") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnName("description") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnName("name") + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnName("owner") + .HasColumnType("INTEGER"); + + b.Property("Visibility") + .HasColumnName("visibility") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.ToTable("timelines"); + }); + + modelBuilder.Entity("Timeline.Entities.TimelineMemberEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("TimelineId") + .HasColumnName("timeline") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnName("user") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("TimelineId"); + + b.HasIndex("UserId"); + + b.ToTable("timeline_members"); + }); + + modelBuilder.Entity("Timeline.Entities.TimelinePostEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnName("author") + .HasColumnType("INTEGER"); + + b.Property("Content") + .HasColumnName("content") + .HasColumnType("TEXT"); + + b.Property("LastUpdated") + .HasColumnName("last_updated") + .HasColumnType("TEXT"); + + b.Property("LocalId") + .HasColumnName("local_id") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnName("time") + .HasColumnType("TEXT"); + + b.Property("TimelineId") + .HasColumnName("timeline") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("TimelineId"); + + b.ToTable("timeline_posts"); + }); + + modelBuilder.Entity("Timeline.Entities.UserAvatarEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("Data") + .HasColumnName("data") + .HasColumnType("BLOB"); + + b.Property("ETag") + .HasColumnName("etag") + .HasColumnType("TEXT"); + + b.Property("LastModified") + .HasColumnName("last_modified") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnName("type") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnName("user") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("user_avatars"); + }); + + modelBuilder.Entity("Timeline.Entities.UserEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnName("id") + .HasColumnType("INTEGER"); + + b.Property("Nickname") + .HasColumnName("nickname") + .HasColumnType("TEXT"); + + b.Property("Password") + .IsRequired() + .HasColumnName("password") + .HasColumnType("TEXT"); + + b.Property("Roles") + .IsRequired() + .HasColumnName("roles") + .HasColumnType("TEXT"); + + b.Property("Username") + .IsRequired() + .HasColumnName("username") + .HasColumnType("TEXT"); + + b.Property("Version") + .ValueGeneratedOnAdd() + .HasColumnName("version") + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.HasKey("Id"); + + b.HasIndex("Username") + .IsUnique(); + + b.ToTable("users"); + }); + + modelBuilder.Entity("Timeline.Entities.TimelineEntity", b => + { + b.HasOne("Timeline.Entities.UserEntity", "Owner") + .WithMany("Timelines") + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Timeline.Entities.TimelineMemberEntity", b => + { + b.HasOne("Timeline.Entities.TimelineEntity", "Timeline") + .WithMany("Members") + .HasForeignKey("TimelineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Timeline.Entities.UserEntity", "User") + .WithMany("TimelinesJoined") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Timeline.Entities.TimelinePostEntity", b => + { + b.HasOne("Timeline.Entities.UserEntity", "Author") + .WithMany("TimelinePosts") + .HasForeignKey("AuthorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Timeline.Entities.TimelineEntity", "Timeline") + .WithMany("Posts") + .HasForeignKey("TimelineId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Timeline.Entities.UserAvatarEntity", b => + { + b.HasOne("Timeline.Entities.UserEntity", "User") + .WithOne("Avatar") + .HasForeignKey("Timeline.Entities.UserAvatarEntity", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Timeline/Migrations/20200229103848_AddPostLocalId.cs b/Timeline/Migrations/20200229103848_AddPostLocalId.cs new file mode 100644 index 00000000..497b38a1 --- /dev/null +++ b/Timeline/Migrations/20200229103848_AddPostLocalId.cs @@ -0,0 +1,42 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Timeline.Migrations +{ + public partial class AddPostLocalId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + + migrationBuilder.AddColumn( + name: "current_post_local_id", + table: "timelines", + nullable: false, + defaultValue: 0L); + + migrationBuilder.AddColumn( + name: "local_id", + table: "timeline_posts", + nullable: false, + defaultValue: 0L); + + migrationBuilder.Sql(@" +UPDATE timeline_posts +SET local_id = (SELECT COUNT (*) + FROM timeline_posts AS p + WHERE p.timeline = timeline_posts.timeline + AND p.id <= timeline_posts.id); + +UPDATE timelines +SET current_post_local_id = (SELECT COUNT (*) + FROM timeline_posts AS p + WHERE p.timeline = timelines.id); + "); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/Timeline/Migrations/DatabaseContextModelSnapshot.cs b/Timeline/Migrations/DatabaseContextModelSnapshot.cs index 2c97ea79..c4b00f47 100644 --- a/Timeline/Migrations/DatabaseContextModelSnapshot.cs +++ b/Timeline/Migrations/DatabaseContextModelSnapshot.cs @@ -23,9 +23,9 @@ namespace Timeline.Migrations .HasColumnName("id") .HasColumnType("INTEGER"); - b.Property("Token") + b.Property("Key") .IsRequired() - .HasColumnName("token") + .HasColumnName("key") .HasColumnType("BLOB"); b.HasKey("Id"); @@ -44,6 +44,10 @@ namespace Timeline.Migrations .HasColumnName("create_time") .HasColumnType("TEXT"); + b.Property("CurrentPostLocalId") + .HasColumnName("current_post_local_id") + .HasColumnType("INTEGER"); + b.Property("Description") .HasColumnName("description") .HasColumnType("TEXT"); @@ -110,6 +114,10 @@ namespace Timeline.Migrations .HasColumnName("last_updated") .HasColumnType("TEXT"); + b.Property("LocalId") + .HasColumnName("local_id") + .HasColumnType("INTEGER"); + b.Property("Time") .HasColumnName("time") .HasColumnType("TEXT"); diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index f12a7fcc..379ec8f5 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -309,6 +309,7 @@ namespace Timeline.Services { return new TimelineEntity { + CurrentPostLocalId = 0, Name = name, OwnerId = owner, Visibility = TimelineVisibility.Register, @@ -386,7 +387,7 @@ namespace Timeline.Services var author = Mapper.Map(await UserService.GetUserById(entity.AuthorId)); posts.Add(new TimelinePostInfo { - Id = entity.Id, + Id = entity.LocalId, Content = entity.Content, Author = author, Time = entity.Time, @@ -405,13 +406,18 @@ namespace Timeline.Services throw new ArgumentNullException(nameof(content)); var timelineId = await FindTimelineId(name); + var timelineEntity = await Database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); + var author = Mapper.Map(await UserService.GetUserById(authorId)); var currentTime = Clock.GetCurrentTime(); var finalTime = time ?? currentTime; + timelineEntity.CurrentPostLocalId += 1; + var postEntity = new TimelinePostEntity { + LocalId = timelineEntity.CurrentPostLocalId, Content = content, AuthorId = authorId, TimelineId = timelineId, @@ -423,7 +429,7 @@ namespace Timeline.Services return new TimelinePostInfo { - Id = postEntity.Id, + Id = postEntity.LocalId, Content = content, Author = author, Time = finalTime, @@ -436,10 +442,9 @@ namespace Timeline.Services if (name == null) throw new ArgumentNullException(nameof(name)); - // Currently we don't use the result. But we need to check the timeline. - var _ = await FindTimelineId(name); + var timelineId = await FindTimelineId(name); - var post = await Database.TimelinePosts.Where(p => p.Id == id).SingleOrDefaultAsync(); + var post = await Database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == id).SingleOrDefaultAsync(); if (post == null) throw new TimelinePostNotExistException(id); -- cgit v1.2.3