20260421045059_IntroduceFeedDomain.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. using System;
  2. using Microsoft.EntityFrameworkCore.Migrations;
  3. #nullable disable
  4. namespace Infrastructure.Migrations.AppDb;
  5. /// <inheritdoc />
  6. public partial class IntroduceFeedDomain : Migration
  7. {
  8. /// <inheritdoc />
  9. protected override void Up(MigrationBuilder migrationBuilder)
  10. {
  11. // ─────────────────────────────────────────────────────────
  12. // 기존 Feed 보드(Board.Code = N'feed') 관련 데이터 전부 삭제
  13. // 새 독립 Feed 도메인으로 이행하는 과정에서 구조 불일치가 있어
  14. // 호환 마이그레이션 대신 구버전 데이터를 명시적으로 제거한다.
  15. // ─────────────────────────────────────────────────────────
  16. migrationBuilder.Sql(@"
  17. DECLARE @FeedBoardID INT = (SELECT TOP 1 ID FROM Board WHERE Code = N'feed');
  18. IF @FeedBoardID IS NOT NULL
  19. BEGIN
  20. -- MemberStats.PostCount 역추적 차감 (feed 보드 작성자별 합계만큼 줄임)
  21. UPDATE MS
  22. SET MS.PostCount = CASE WHEN MS.PostCount > cnt.cnt THEN MS.PostCount - cnt.cnt ELSE 0 END
  23. FROM MemberStats MS
  24. INNER JOIN (
  25. SELECT MemberID, COUNT(*) AS cnt
  26. FROM Post
  27. WHERE BoardID = @FeedBoardID AND MemberID IS NOT NULL
  28. GROUP BY MemberID
  29. ) cnt ON MS.MemberID = cnt.MemberID;
  30. -- Tag.UsageCount 역추적 차감 (feed 보드 포스트가 사용한 태그 횟수만큼 줄임)
  31. UPDATE T
  32. SET T.UsageCount = CASE WHEN T.UsageCount > cnt.cnt THEN T.UsageCount - cnt.cnt ELSE 0 END
  33. FROM Tag T
  34. INNER JOIN (
  35. SELECT PT.TagID, COUNT(*) AS cnt
  36. FROM PostTag PT
  37. INNER JOIN Post P ON PT.PostID = P.ID
  38. WHERE P.BoardID = @FeedBoardID
  39. GROUP BY PT.TagID
  40. ) cnt ON T.ID = cnt.TagID;
  41. -- Post 삭제 (Cascade로 PostImage/Media/File/Link/Tag/Reaction/Bookmark/Report/Comment 등 전부 삭제)
  42. DELETE FROM Post WHERE BoardID = @FeedBoardID;
  43. -- Board 부속 엔티티 삭제
  44. DELETE FROM BoardPrefix WHERE BoardID = @FeedBoardID;
  45. DELETE FROM BoardManager WHERE BoardID = @FeedBoardID;
  46. DELETE FROM BoardMeta WHERE BoardID = @FeedBoardID;
  47. -- Board 자체 삭제
  48. DELETE FROM Board WHERE ID = @FeedBoardID;
  49. END;
  50. ");
  51. migrationBuilder.CreateTable(
  52. name: "FeedPost",
  53. columns: table => new
  54. {
  55. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  56. .Annotation("SqlServer:Identity", "1, 1"),
  57. MemberID = table.Column<int>(type: "int", nullable: false, comment: "작성 회원 ID"),
  58. Content = table.Column<string>(type: "nvarchar(max)", maxLength: 5000, nullable: false, comment: "본문"),
  59. Thumbnail = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: true, comment: "썸네일 URL"),
  60. Images = table.Column<byte>(type: "tinyint", nullable: false, comment: "이미지 개수"),
  61. Medias = table.Column<byte>(type: "tinyint", nullable: false, comment: "미디어 개수"),
  62. Tags = table.Column<byte>(type: "tinyint", nullable: false, comment: "태그 개수"),
  63. Likes = table.Column<int>(type: "int", nullable: false, comment: "좋아요 수"),
  64. Comments = table.Column<int>(type: "int", nullable: false, comment: "댓글 수"),
  65. Bookmarks = table.Column<int>(type: "int", nullable: false, comment: "북마크 수"),
  66. Views = table.Column<int>(type: "int", nullable: false, comment: "조회수"),
  67. Reports = table.Column<int>(type: "int", nullable: false, comment: "신고 수"),
  68. IsDeleted = table.Column<bool>(type: "bit", nullable: false, comment: "삭제 여부"),
  69. IpAddress = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true, comment: "작성자 IP"),
  70. UserAgent = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true, comment: "작성자 User-Agent"),
  71. DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "삭제 일시"),
  72. UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
  73. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
  74. },
  75. constraints: table =>
  76. {
  77. table.PrimaryKey("PK_FeedPost", x => x.ID);
  78. table.ForeignKey(
  79. name: "FK_FeedPost_Member_MemberID",
  80. column: x => x.MemberID,
  81. principalTable: "Member",
  82. principalColumn: "ID",
  83. onDelete: ReferentialAction.Restrict);
  84. },
  85. comment: "피드 포스트");
  86. migrationBuilder.CreateTable(
  87. name: "FeedTag",
  88. columns: table => new
  89. {
  90. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  91. .Annotation("SqlServer:Identity", "1, 1"),
  92. Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false, comment: "태그 이름"),
  93. Slug = table.Column<string>(type: "nvarchar(120)", maxLength: 120, nullable: false, comment: "태그 슬러그 (URL용)"),
  94. UsageCount = table.Column<long>(type: "bigint", nullable: false, comment: "사용 횟수"),
  95. UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
  96. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
  97. },
  98. constraints: table =>
  99. {
  100. table.PrimaryKey("PK_FeedTag", x => x.ID);
  101. },
  102. comment: "피드 태그 마스터");
  103. migrationBuilder.CreateTable(
  104. name: "FeedBookmark",
  105. columns: table => new
  106. {
  107. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  108. .Annotation("SqlServer:Identity", "1, 1"),
  109. FeedPostID = table.Column<int>(type: "int", nullable: false),
  110. MemberID = table.Column<int>(type: "int", nullable: false),
  111. IpAddress = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
  112. UserAgent = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true),
  113. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  114. },
  115. constraints: table =>
  116. {
  117. table.PrimaryKey("PK_FeedBookmark", x => x.ID);
  118. table.ForeignKey(
  119. name: "FK_FeedBookmark_FeedPost_FeedPostID",
  120. column: x => x.FeedPostID,
  121. principalTable: "FeedPost",
  122. principalColumn: "ID",
  123. onDelete: ReferentialAction.Cascade);
  124. table.ForeignKey(
  125. name: "FK_FeedBookmark_Member_MemberID",
  126. column: x => x.MemberID,
  127. principalTable: "Member",
  128. principalColumn: "ID",
  129. onDelete: ReferentialAction.Cascade);
  130. },
  131. comment: "피드 포스트 북마크");
  132. migrationBuilder.CreateTable(
  133. name: "FeedComment",
  134. columns: table => new
  135. {
  136. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  137. .Annotation("SqlServer:Identity", "1, 1"),
  138. FeedPostID = table.Column<int>(type: "int", nullable: false, comment: "FeedPost ID"),
  139. MemberID = table.Column<int>(type: "int", nullable: false, comment: "작성 회원 ID"),
  140. ParentID = table.Column<int>(type: "int", nullable: true, comment: "부모 댓글 ID (대댓글용)"),
  141. Depth = table.Column<short>(type: "smallint", nullable: false, comment: "중첩 깊이 (0 = 루트)"),
  142. Content = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false, comment: "댓글 내용"),
  143. Likes = table.Column<int>(type: "int", nullable: false, comment: "좋아요 수"),
  144. Replies = table.Column<int>(type: "int", nullable: false, comment: "자식 댓글 수"),
  145. Reports = table.Column<int>(type: "int", nullable: false, comment: "신고 수"),
  146. Score = table.Column<int>(type: "int", nullable: false, comment: "랭킹 스코어"),
  147. IsDeleted = table.Column<bool>(type: "bit", nullable: false, comment: "삭제 여부"),
  148. IpAddress = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
  149. UserAgent = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true),
  150. DeletedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "삭제 일시"),
  151. UpdatedAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "수정 일시"),
  152. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false, comment: "등록 일시")
  153. },
  154. constraints: table =>
  155. {
  156. table.PrimaryKey("PK_FeedComment", x => x.ID);
  157. table.ForeignKey(
  158. name: "FK_FeedComment_FeedComment_ParentID",
  159. column: x => x.ParentID,
  160. principalTable: "FeedComment",
  161. principalColumn: "ID",
  162. onDelete: ReferentialAction.Restrict);
  163. table.ForeignKey(
  164. name: "FK_FeedComment_FeedPost_FeedPostID",
  165. column: x => x.FeedPostID,
  166. principalTable: "FeedPost",
  167. principalColumn: "ID",
  168. onDelete: ReferentialAction.Cascade);
  169. table.ForeignKey(
  170. name: "FK_FeedComment_Member_MemberID",
  171. column: x => x.MemberID,
  172. principalTable: "Member",
  173. principalColumn: "ID",
  174. onDelete: ReferentialAction.Restrict);
  175. },
  176. comment: "피드 댓글 (Reddit식 계층형)");
  177. migrationBuilder.CreateTable(
  178. name: "FeedLike",
  179. columns: table => new
  180. {
  181. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  182. .Annotation("SqlServer:Identity", "1, 1"),
  183. FeedPostID = table.Column<int>(type: "int", nullable: false),
  184. MemberID = table.Column<int>(type: "int", nullable: false),
  185. IpAddress = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
  186. UserAgent = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true),
  187. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  188. },
  189. constraints: table =>
  190. {
  191. table.PrimaryKey("PK_FeedLike", x => x.ID);
  192. table.ForeignKey(
  193. name: "FK_FeedLike_FeedPost_FeedPostID",
  194. column: x => x.FeedPostID,
  195. principalTable: "FeedPost",
  196. principalColumn: "ID",
  197. onDelete: ReferentialAction.Cascade);
  198. table.ForeignKey(
  199. name: "FK_FeedLike_Member_MemberID",
  200. column: x => x.MemberID,
  201. principalTable: "Member",
  202. principalColumn: "ID",
  203. onDelete: ReferentialAction.Cascade);
  204. },
  205. comment: "피드 포스트 좋아요");
  206. migrationBuilder.CreateTable(
  207. name: "FeedPostImage",
  208. columns: table => new
  209. {
  210. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  211. .Annotation("SqlServer:Identity", "1, 1"),
  212. FeedPostID = table.Column<int>(type: "int", nullable: false),
  213. UUID = table.Column<Guid>(type: "uniqueidentifier", nullable: false, comment: "UUID"),
  214. FileName = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false, comment: "원본 파일명"),
  215. HashedName = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: false, comment: "저장 파일명(해시)"),
  216. Path = table.Column<string>(type: "nvarchar(500)", maxLength: 500, nullable: false, comment: "상대 경로"),
  217. Url = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: false, comment: "접근 URL"),
  218. Extension = table.Column<string>(type: "nvarchar(10)", maxLength: 10, nullable: true, comment: "확장자"),
  219. ContentType = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true, comment: "MIME"),
  220. Size = table.Column<long>(type: "bigint", nullable: true, comment: "바이트 크기"),
  221. Width = table.Column<short>(type: "smallint", nullable: true, comment: "가로 픽셀"),
  222. Height = table.Column<short>(type: "smallint", nullable: true, comment: "세로 픽셀"),
  223. IsDisabled = table.Column<bool>(type: "bit", nullable: false, comment: "비활성 여부"),
  224. DisabledAt = table.Column<DateTime>(type: "datetime2", nullable: true, comment: "비활성 일시"),
  225. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  226. },
  227. constraints: table =>
  228. {
  229. table.PrimaryKey("PK_FeedPostImage", x => x.ID);
  230. table.ForeignKey(
  231. name: "FK_FeedPostImage_FeedPost_FeedPostID",
  232. column: x => x.FeedPostID,
  233. principalTable: "FeedPost",
  234. principalColumn: "ID",
  235. onDelete: ReferentialAction.Cascade);
  236. },
  237. comment: "피드 포스트 이미지");
  238. migrationBuilder.CreateTable(
  239. name: "FeedPostMedia",
  240. columns: table => new
  241. {
  242. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  243. .Annotation("SqlServer:Identity", "1, 1"),
  244. FeedPostID = table.Column<int>(type: "int", nullable: false),
  245. Url = table.Column<string>(type: "nvarchar(1000)", maxLength: 1000, nullable: false, comment: "미디어 URL"),
  246. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  247. },
  248. constraints: table =>
  249. {
  250. table.PrimaryKey("PK_FeedPostMedia", x => x.ID);
  251. table.ForeignKey(
  252. name: "FK_FeedPostMedia_FeedPost_FeedPostID",
  253. column: x => x.FeedPostID,
  254. principalTable: "FeedPost",
  255. principalColumn: "ID",
  256. onDelete: ReferentialAction.Cascade);
  257. },
  258. comment: "피드 포스트 미디어 링크");
  259. migrationBuilder.CreateTable(
  260. name: "FeedPostMention",
  261. columns: table => new
  262. {
  263. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  264. .Annotation("SqlServer:Identity", "1, 1"),
  265. FeedPostID = table.Column<int>(type: "int", nullable: false),
  266. MemberID = table.Column<int>(type: "int", nullable: false),
  267. RawHandle = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false, comment: "원문 @handle"),
  268. Start = table.Column<int>(type: "int", nullable: false, comment: "본문 내 시작 인덱스"),
  269. Length = table.Column<int>(type: "int", nullable: false, comment: "길이"),
  270. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  271. },
  272. constraints: table =>
  273. {
  274. table.PrimaryKey("PK_FeedPostMention", x => x.ID);
  275. table.ForeignKey(
  276. name: "FK_FeedPostMention_FeedPost_FeedPostID",
  277. column: x => x.FeedPostID,
  278. principalTable: "FeedPost",
  279. principalColumn: "ID",
  280. onDelete: ReferentialAction.Cascade);
  281. table.ForeignKey(
  282. name: "FK_FeedPostMention_Member_MemberID",
  283. column: x => x.MemberID,
  284. principalTable: "Member",
  285. principalColumn: "ID",
  286. onDelete: ReferentialAction.Cascade);
  287. },
  288. comment: "피드 포스트 멘션");
  289. migrationBuilder.CreateTable(
  290. name: "FeedPostTag",
  291. columns: table => new
  292. {
  293. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  294. .Annotation("SqlServer:Identity", "1, 1"),
  295. FeedPostID = table.Column<int>(type: "int", nullable: false),
  296. FeedTagID = table.Column<int>(type: "int", nullable: false),
  297. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  298. },
  299. constraints: table =>
  300. {
  301. table.PrimaryKey("PK_FeedPostTag", x => x.ID);
  302. table.ForeignKey(
  303. name: "FK_FeedPostTag_FeedPost_FeedPostID",
  304. column: x => x.FeedPostID,
  305. principalTable: "FeedPost",
  306. principalColumn: "ID",
  307. onDelete: ReferentialAction.Cascade);
  308. table.ForeignKey(
  309. name: "FK_FeedPostTag_FeedTag_FeedTagID",
  310. column: x => x.FeedTagID,
  311. principalTable: "FeedTag",
  312. principalColumn: "ID",
  313. onDelete: ReferentialAction.Cascade);
  314. },
  315. comment: "피드 포스트-태그 조인");
  316. migrationBuilder.CreateTable(
  317. name: "FeedCommentLike",
  318. columns: table => new
  319. {
  320. ID = table.Column<int>(type: "int", nullable: false, comment: "PK")
  321. .Annotation("SqlServer:Identity", "1, 1"),
  322. FeedPostID = table.Column<int>(type: "int", nullable: false),
  323. FeedCommentID = table.Column<int>(type: "int", nullable: false),
  324. MemberID = table.Column<int>(type: "int", nullable: false),
  325. IpAddress = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
  326. UserAgent = table.Column<string>(type: "nvarchar(255)", maxLength: 255, nullable: true),
  327. CreatedAt = table.Column<DateTime>(type: "datetime2", nullable: false)
  328. },
  329. constraints: table =>
  330. {
  331. table.PrimaryKey("PK_FeedCommentLike", x => x.ID);
  332. table.ForeignKey(
  333. name: "FK_FeedCommentLike_FeedComment_FeedCommentID",
  334. column: x => x.FeedCommentID,
  335. principalTable: "FeedComment",
  336. principalColumn: "ID",
  337. onDelete: ReferentialAction.Cascade);
  338. table.ForeignKey(
  339. name: "FK_FeedCommentLike_FeedPost_FeedPostID",
  340. column: x => x.FeedPostID,
  341. principalTable: "FeedPost",
  342. principalColumn: "ID",
  343. onDelete: ReferentialAction.Restrict);
  344. table.ForeignKey(
  345. name: "FK_FeedCommentLike_Member_MemberID",
  346. column: x => x.MemberID,
  347. principalTable: "Member",
  348. principalColumn: "ID",
  349. onDelete: ReferentialAction.Cascade);
  350. },
  351. comment: "피드 댓글 좋아요");
  352. migrationBuilder.CreateIndex(
  353. name: "IX_FeedBookmark_FeedPostID",
  354. table: "FeedBookmark",
  355. column: "FeedPostID");
  356. migrationBuilder.CreateIndex(
  357. name: "IX_FeedBookmark_FeedPostID_MemberID",
  358. table: "FeedBookmark",
  359. columns: new[] { "FeedPostID", "MemberID" },
  360. unique: true);
  361. migrationBuilder.CreateIndex(
  362. name: "IX_FeedBookmark_MemberID",
  363. table: "FeedBookmark",
  364. column: "MemberID");
  365. migrationBuilder.CreateIndex(
  366. name: "IX_FeedBookmark_MemberID_CreatedAt",
  367. table: "FeedBookmark",
  368. columns: new[] { "MemberID", "CreatedAt" },
  369. descending: new[] { false, true });
  370. migrationBuilder.CreateIndex(
  371. name: "IX_FeedComment_FeedPostID",
  372. table: "FeedComment",
  373. column: "FeedPostID");
  374. migrationBuilder.CreateIndex(
  375. name: "IX_FeedComment_FeedPostID_IsDeleted_ParentID_CreatedAt",
  376. table: "FeedComment",
  377. columns: new[] { "FeedPostID", "IsDeleted", "ParentID", "CreatedAt" },
  378. descending: new[] { false, false, false, true });
  379. migrationBuilder.CreateIndex(
  380. name: "IX_FeedComment_FeedPostID_IsDeleted_ParentID_Score_ID",
  381. table: "FeedComment",
  382. columns: new[] { "FeedPostID", "IsDeleted", "ParentID", "Score", "ID" },
  383. descending: new[] { false, false, false, true, true });
  384. migrationBuilder.CreateIndex(
  385. name: "IX_FeedComment_FeedPostID_MemberID_IsDeleted_ParentID_CreatedAt",
  386. table: "FeedComment",
  387. columns: new[] { "FeedPostID", "MemberID", "IsDeleted", "ParentID", "CreatedAt" },
  388. descending: new[] { false, false, false, false, true });
  389. migrationBuilder.CreateIndex(
  390. name: "IX_FeedComment_MemberID",
  391. table: "FeedComment",
  392. column: "MemberID");
  393. migrationBuilder.CreateIndex(
  394. name: "IX_FeedComment_ParentID",
  395. table: "FeedComment",
  396. column: "ParentID");
  397. migrationBuilder.CreateIndex(
  398. name: "IX_FeedCommentLike_FeedCommentID",
  399. table: "FeedCommentLike",
  400. column: "FeedCommentID");
  401. migrationBuilder.CreateIndex(
  402. name: "IX_FeedCommentLike_FeedCommentID_MemberID",
  403. table: "FeedCommentLike",
  404. columns: new[] { "FeedCommentID", "MemberID" },
  405. unique: true);
  406. migrationBuilder.CreateIndex(
  407. name: "IX_FeedCommentLike_FeedPostID",
  408. table: "FeedCommentLike",
  409. column: "FeedPostID");
  410. migrationBuilder.CreateIndex(
  411. name: "IX_FeedCommentLike_MemberID",
  412. table: "FeedCommentLike",
  413. column: "MemberID");
  414. migrationBuilder.CreateIndex(
  415. name: "IX_FeedLike_FeedPostID",
  416. table: "FeedLike",
  417. column: "FeedPostID");
  418. migrationBuilder.CreateIndex(
  419. name: "IX_FeedLike_FeedPostID_MemberID",
  420. table: "FeedLike",
  421. columns: new[] { "FeedPostID", "MemberID" },
  422. unique: true);
  423. migrationBuilder.CreateIndex(
  424. name: "IX_FeedLike_MemberID",
  425. table: "FeedLike",
  426. column: "MemberID");
  427. migrationBuilder.CreateIndex(
  428. name: "IX_FeedPost_CreatedAt",
  429. table: "FeedPost",
  430. column: "CreatedAt");
  431. migrationBuilder.CreateIndex(
  432. name: "IX_FeedPost_IsDeleted",
  433. table: "FeedPost",
  434. column: "IsDeleted");
  435. migrationBuilder.CreateIndex(
  436. name: "IX_FeedPost_IsDeleted_CreatedAt",
  437. table: "FeedPost",
  438. columns: new[] { "IsDeleted", "CreatedAt" });
  439. migrationBuilder.CreateIndex(
  440. name: "IX_FeedPost_IsDeleted_Likes_Comments_Views",
  441. table: "FeedPost",
  442. columns: new[] { "IsDeleted", "Likes", "Comments", "Views" });
  443. migrationBuilder.CreateIndex(
  444. name: "IX_FeedPost_MemberID",
  445. table: "FeedPost",
  446. column: "MemberID");
  447. migrationBuilder.CreateIndex(
  448. name: "IX_FeedPost_MemberID_IsDeleted_CreatedAt",
  449. table: "FeedPost",
  450. columns: new[] { "MemberID", "IsDeleted", "CreatedAt" });
  451. migrationBuilder.CreateIndex(
  452. name: "IX_FeedPostImage_FeedPostID",
  453. table: "FeedPostImage",
  454. column: "FeedPostID");
  455. migrationBuilder.CreateIndex(
  456. name: "IX_FeedPostImage_FeedPostID_HashedName",
  457. table: "FeedPostImage",
  458. columns: new[] { "FeedPostID", "HashedName" });
  459. migrationBuilder.CreateIndex(
  460. name: "IX_FeedPostImage_FeedPostID_IsDisabled",
  461. table: "FeedPostImage",
  462. columns: new[] { "FeedPostID", "IsDisabled" });
  463. migrationBuilder.CreateIndex(
  464. name: "IX_FeedPostImage_UUID",
  465. table: "FeedPostImage",
  466. column: "UUID",
  467. unique: true);
  468. migrationBuilder.CreateIndex(
  469. name: "IX_FeedPostMedia_FeedPostID",
  470. table: "FeedPostMedia",
  471. column: "FeedPostID");
  472. migrationBuilder.CreateIndex(
  473. name: "IX_FeedPostMention_FeedPostID",
  474. table: "FeedPostMention",
  475. column: "FeedPostID");
  476. migrationBuilder.CreateIndex(
  477. name: "IX_FeedPostMention_FeedPostID_MemberID",
  478. table: "FeedPostMention",
  479. columns: new[] { "FeedPostID", "MemberID" },
  480. unique: true);
  481. migrationBuilder.CreateIndex(
  482. name: "IX_FeedPostMention_MemberID",
  483. table: "FeedPostMention",
  484. column: "MemberID");
  485. migrationBuilder.CreateIndex(
  486. name: "IX_FeedPostMention_MemberID_CreatedAt",
  487. table: "FeedPostMention",
  488. columns: new[] { "MemberID", "CreatedAt" },
  489. descending: new[] { false, true });
  490. migrationBuilder.CreateIndex(
  491. name: "IX_FeedPostTag_FeedPostID",
  492. table: "FeedPostTag",
  493. column: "FeedPostID");
  494. migrationBuilder.CreateIndex(
  495. name: "IX_FeedPostTag_FeedPostID_FeedTagID",
  496. table: "FeedPostTag",
  497. columns: new[] { "FeedPostID", "FeedTagID" },
  498. unique: true);
  499. migrationBuilder.CreateIndex(
  500. name: "IX_FeedPostTag_FeedTagID",
  501. table: "FeedPostTag",
  502. column: "FeedTagID");
  503. migrationBuilder.CreateIndex(
  504. name: "IX_FeedPostTag_FeedTagID_CreatedAt",
  505. table: "FeedPostTag",
  506. columns: new[] { "FeedTagID", "CreatedAt" },
  507. descending: new[] { false, true });
  508. migrationBuilder.CreateIndex(
  509. name: "IX_FeedTag_Name",
  510. table: "FeedTag",
  511. column: "Name",
  512. unique: true);
  513. migrationBuilder.CreateIndex(
  514. name: "IX_FeedTag_Slug",
  515. table: "FeedTag",
  516. column: "Slug",
  517. unique: true);
  518. migrationBuilder.CreateIndex(
  519. name: "IX_FeedTag_UsageCount",
  520. table: "FeedTag",
  521. column: "UsageCount",
  522. descending: new bool[0]);
  523. }
  524. /// <inheritdoc />
  525. protected override void Down(MigrationBuilder migrationBuilder)
  526. {
  527. migrationBuilder.DropTable(
  528. name: "FeedBookmark");
  529. migrationBuilder.DropTable(
  530. name: "FeedCommentLike");
  531. migrationBuilder.DropTable(
  532. name: "FeedLike");
  533. migrationBuilder.DropTable(
  534. name: "FeedPostImage");
  535. migrationBuilder.DropTable(
  536. name: "FeedPostMedia");
  537. migrationBuilder.DropTable(
  538. name: "FeedPostMention");
  539. migrationBuilder.DropTable(
  540. name: "FeedPostTag");
  541. migrationBuilder.DropTable(
  542. name: "FeedComment");
  543. migrationBuilder.DropTable(
  544. name: "FeedTag");
  545. migrationBuilder.DropTable(
  546. name: "FeedPost");
  547. }
  548. }