using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; namespace MessageService.Infrastructure.Migrations { [DbContext(typeof(MessageDbContext))] [Migration("20260911000100_ConversationUniqueness")] public partial class ConversationUniqueness : Migration { protected override void Up(MigrationBuilder migrationBuilder) { migrationBuilder.Sql(""" CREATE TEMPORARY TABLE `conversation_dedup` AS SELECT `Id`, ROW_NUMBER() OVER ( PARTITION BY `UserId`, `ChatType`, `TargetId` ORDER BY COALESCE(`ModificationTime`, `CreationTime`) DESC, `Id` DESC ) AS `row_num`, MAX(`UnreadCount`) OVER ( PARTITION BY `UserId`, `ChatType`, `TargetId` ) AS `max_unread_count`, MAX(`LastReadSequenceId`) OVER ( PARTITION BY `UserId`, `ChatType`, `TargetId` ) AS `max_last_read_sequence_id` FROM `conversations` WHERE `IsDeleted` = 0; """); migrationBuilder.Sql(""" UPDATE `conversations` AS `conversation` INNER JOIN `conversation_dedup` AS `dedup` ON `conversation`.`Id` = `dedup`.`Id` SET `conversation`.`UnreadCount` = CASE WHEN `dedup`.`row_num` = 1 THEN `dedup`.`max_unread_count` ELSE `conversation`.`UnreadCount` END, `conversation`.`LastReadSequenceId` = CASE WHEN `dedup`.`row_num` = 1 THEN `dedup`.`max_last_read_sequence_id` ELSE `conversation`.`LastReadSequenceId` END, `conversation`.`IsDeleted` = CASE WHEN `dedup`.`row_num` = 1 THEN `conversation`.`IsDeleted` ELSE 1 END, `conversation`.`Deletion` = CASE WHEN `dedup`.`row_num` = 1 THEN `conversation`.`Deletion` ELSE CURRENT_TIMESTAMP(6) END; """); migrationBuilder.Sql("DROP TEMPORARY TABLE `conversation_dedup`;"); migrationBuilder.AddColumn( name: "ActiveConversationKey", table: "conversations", type: "varchar(96)", maxLength: 96, nullable: true, computedColumnSql: "CASE WHEN `IsDeleted` = 0 THEN CONCAT(`UserId`, ':', `ChatType`, ':', `TargetId`) ELSE NULL END", stored: true); migrationBuilder.CreateIndex( name: "UX_conversations_ActiveConversationKey", table: "conversations", column: "ActiveConversationKey", unique: true); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropIndex( name: "UX_conversations_ActiveConversationKey", table: "conversations"); migrationBuilder.DropColumn( name: "ActiveConversationKey", table: "conversations"); } } }