From 30f57ff50ec5033325c97ebdcaca6ddadcd2d04e Mon Sep 17 00:00:00 2001 From: XShine555 Date: Mon, 1 Jun 2026 22:04:52 +0200 Subject: [PATCH] Auto-set CreatedAt/UpdatedAt via EF interceptor; standardize timestamp names across entities --- .../GetPlayListsByUserIdQueryHandler.cs | 2 +- .../Responses/PlayListApplicationResponse.cs | 4 +- .../Handlers/GetTracksByUserIdQueryHandler.cs | 2 +- .../Responses/TrackApplicationResponse.cs | 8 +- .../Users/Handlers/SyncUserCommandHandler.cs | 1 - Domain/Abstractions/IAuditable.cs | 9 + Domain/Entities/PlayList.cs | 7 +- Domain/Entities/Track.cs | 7 +- Domain/Entities/User.cs | 3 +- .../Persistence/AuditableEntityInterceptor.cs | 43 ++ Infrastructure/Persistence/Database.cs | 1 + ...95757_RenameTimestampsAndAudit.Designer.cs | 583 ++++++++++++++++++ ...20260601195757_RenameTimestampsAndAudit.cs | 58 ++ .../Migrations/DatabaseModelSnapshot.cs | 8 +- 14 files changed, 716 insertions(+), 20 deletions(-) create mode 100644 Domain/Abstractions/IAuditable.cs create mode 100644 Infrastructure/Persistence/AuditableEntityInterceptor.cs create mode 100644 Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.Designer.cs create mode 100644 Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.cs diff --git a/Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs b/Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs index a5f9123..d4b571c 100644 --- a/Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs +++ b/Application/PlayLists/Handlers/GetPlayListsByUserIdQueryHandler.cs @@ -27,7 +27,7 @@ namespace Musify.Application.PlayLists.Handlers var totalCount = await playListsQuery.CountAsync(cancellationToken); var pagedPlayLists = await playListsQuery - .OrderBy(p => p.CreatedDate) + .OrderBy(p => p.CreatedAt) .Select(p => PlayListApplicationResponse.FromEntity(p)) .ToPagedListAsync(request.PageNumber, request.PageSize, totalCount, cancellationToken); diff --git a/Application/PlayLists/Responses/PlayListApplicationResponse.cs b/Application/PlayLists/Responses/PlayListApplicationResponse.cs index 994996a..6a577b4 100644 --- a/Application/PlayLists/Responses/PlayListApplicationResponse.cs +++ b/Application/PlayLists/Responses/PlayListApplicationResponse.cs @@ -21,8 +21,8 @@ namespace Musify.Application.PlayLists.Responses playList.SmallPictureName, playList.MediumPictureName, playList.LargePictureName, - playList.CreatedDate, - playList.UpdatedDate); + playList.CreatedAt, + playList.UpdatedAt); } } } \ No newline at end of file diff --git a/Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs b/Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs index bf76206..5822428 100644 --- a/Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs +++ b/Application/Tracks/Handlers/GetTracksByUserIdQueryHandler.cs @@ -31,7 +31,7 @@ namespace Musify.Application.Tracks.Handlers var totalCount = await tracksQuery.CountAsync(cancellationToken); var pagedTracks = await tracksQuery - .OrderBy(t => t.Track.CreatedDate) + .OrderBy(t => t.Track.CreatedAt) .Select(t => TrackApplicationResponse.FromEntity(t.Track)) .ToPagedListAsync(pageNumber, pageSize, totalCount, cancellationToken); diff --git a/Application/Tracks/Responses/TrackApplicationResponse.cs b/Application/Tracks/Responses/TrackApplicationResponse.cs index 33d8a83..83d3fa7 100644 --- a/Application/Tracks/Responses/TrackApplicationResponse.cs +++ b/Application/Tracks/Responses/TrackApplicationResponse.cs @@ -5,16 +5,16 @@ namespace Musify.Application.Tracks.Responses public record TrackApplicationResponse( Guid Id, string Title, - DateTime CreatedDate, - DateTime UpdatedDate) + DateTime CreatedAt, + DateTime UpdatedAt) { public static TrackApplicationResponse FromEntity(Track track) { return new TrackApplicationResponse( track.Id, track.Title, - track.CreatedDate, - track.UpdatedDate); + track.CreatedAt, + track.UpdatedAt); } } } \ No newline at end of file diff --git a/Application/Users/Handlers/SyncUserCommandHandler.cs b/Application/Users/Handlers/SyncUserCommandHandler.cs index cbeeee5..0686829 100644 --- a/Application/Users/Handlers/SyncUserCommandHandler.cs +++ b/Application/Users/Handlers/SyncUserCommandHandler.cs @@ -63,7 +63,6 @@ namespace Musify.Application.Users.Handlers if (hasChanges) { - user.UpdatedAt = DateTime.UtcNow; await database.SaveChangesAsync(cancellationToken); logger.LogInformation("Synced profile for user {UserId}", request.Id); } diff --git a/Domain/Abstractions/IAuditable.cs b/Domain/Abstractions/IAuditable.cs new file mode 100644 index 0000000..4815e2c --- /dev/null +++ b/Domain/Abstractions/IAuditable.cs @@ -0,0 +1,9 @@ +namespace Musify.Domain.Abstractions +{ + public interface IAuditable + { + DateTime CreatedAt { get; set; } + + DateTime UpdatedAt { get; set; } + } +} diff --git a/Domain/Entities/PlayList.cs b/Domain/Entities/PlayList.cs index 8789adb..cf3d509 100644 --- a/Domain/Entities/PlayList.cs +++ b/Domain/Entities/PlayList.cs @@ -1,13 +1,14 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Musify.Domain.Abstractions; using Musify.Domain.ValueObjects; namespace Musify.Domain.Entities { #pragma warning disable CS8618 [Table("PlayLists")] - public class PlayList + public class PlayList : IAuditable { [Key] public Guid Id { get; set; } = Guid.NewGuid(); @@ -47,10 +48,10 @@ namespace Musify.Domain.Entities public LifeCycleStatus LifeCycleStatus { get; set; } = LifeCycleStatus.Active; [Required] - public DateTime CreatedDate { get; set; } = DateTime.UtcNow; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Required] - public DateTime UpdatedDate { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; [ForeignKey(nameof(UserId)) ] public User User { get; set; } diff --git a/Domain/Entities/Track.cs b/Domain/Entities/Track.cs index c569b5a..8299c3d 100644 --- a/Domain/Entities/Track.cs +++ b/Domain/Entities/Track.cs @@ -2,12 +2,13 @@ using System.ComponentModel.DataAnnotations.Schema; using System.Diagnostics.CodeAnalysis; +using Musify.Domain.Abstractions; using Musify.Domain.ValueObjects; namespace Musify.Domain.Entities { #pragma warning disable CS8618 - public class Track + public class Track : IAuditable { [Key] public Guid Id { get; set; } = Guid.NewGuid(); @@ -55,10 +56,10 @@ namespace Musify.Domain.Entities public DateTime? LastRetryAt { get; set; } [Required] - public DateTime CreatedDate { get; set; } = DateTime.UtcNow; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; [Required] - public DateTime UpdatedDate { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; public ICollection UserTracks { get; set; } = new List(); diff --git a/Domain/Entities/User.cs b/Domain/Entities/User.cs index 48408ff..184dbc6 100644 --- a/Domain/Entities/User.cs +++ b/Domain/Entities/User.cs @@ -1,10 +1,11 @@ using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using Musify.Domain.Abstractions; namespace Musify.Domain.Entities { [Table("User")] - public class User + public class User : IAuditable { [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] diff --git a/Infrastructure/Persistence/AuditableEntityInterceptor.cs b/Infrastructure/Persistence/AuditableEntityInterceptor.cs new file mode 100644 index 0000000..40c7e69 --- /dev/null +++ b/Infrastructure/Persistence/AuditableEntityInterceptor.cs @@ -0,0 +1,43 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Musify.Domain.Abstractions; + +namespace Musify.Infrastructure.Persistence +{ + public sealed class AuditableEntityInterceptor : SaveChangesInterceptor + { + public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) + { + ApplyTimestamps(eventData.Context); + return base.SavingChanges(eventData, result); + } + + public override ValueTask> SavingChangesAsync( + DbContextEventData eventData, InterceptionResult result, CancellationToken cancellationToken = default) + { + ApplyTimestamps(eventData.Context); + return base.SavingChangesAsync(eventData, result, cancellationToken); + } + + private static void ApplyTimestamps(DbContext? context) + { + if (context is null) + return; + + var now = DateTime.UtcNow; + + foreach (var entry in context.ChangeTracker.Entries()) + { + if (entry.State == EntityState.Added) + { + entry.Entity.CreatedAt = now; + entry.Entity.UpdatedAt = now; + } + else if (entry.State == EntityState.Modified) + { + entry.Entity.UpdatedAt = now; + } + } + } + } +} diff --git a/Infrastructure/Persistence/Database.cs b/Infrastructure/Persistence/Database.cs index 98f1ea1..3723077 100644 --- a/Infrastructure/Persistence/Database.cs +++ b/Infrastructure/Persistence/Database.cs @@ -14,6 +14,7 @@ namespace Musify.Infrastructure.Persistence protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql(configuration.ConnectionString); + optionsBuilder.AddInterceptors(new AuditableEntityInterceptor()); } protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.Designer.cs b/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.Designer.cs new file mode 100644 index 0000000..279f318 --- /dev/null +++ b/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.Designer.cs @@ -0,0 +1,583 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Musify.Infrastructure.Persistence; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Musify.Infrastructure.Persistence.Migrations +{ + [DbContext(typeof(Database))] + [Migration("20260601195757_RenameTimestampsAndAudit")] + partial class RenameTimestampsAndAudit + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.InboxState", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Consumed") + .HasColumnType("timestamp with time zone"); + + b.Property("ConsumerId") + .HasColumnType("uuid"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LastSequenceNumber") + .HasColumnType("bigint"); + + b.Property("LockId") + .HasColumnType("uuid"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("ReceiveCount") + .HasColumnType("integer"); + + b.Property("Received") + .HasColumnType("timestamp with time zone"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea"); + + b.HasKey("Id"); + + b.HasIndex("Delivered"); + + b.ToTable("InboxState"); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => + { + b.Property("SequenceNumber") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SequenceNumber")); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ConversationId") + .HasColumnType("uuid"); + + b.Property("CorrelationId") + .HasColumnType("uuid"); + + b.Property("DestinationAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EnqueueTime") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone"); + + b.Property("FaultAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Headers") + .HasColumnType("text"); + + b.Property("InboxConsumerId") + .HasColumnType("uuid"); + + b.Property("InboxMessageId") + .HasColumnType("uuid"); + + b.Property("InitiatorId") + .HasColumnType("uuid"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("MessageType") + .IsRequired() + .HasColumnType("text"); + + b.Property("OutboxId") + .HasColumnType("uuid"); + + b.Property("Properties") + .HasColumnType("text"); + + b.Property("RequestId") + .HasColumnType("uuid"); + + b.Property("ResponseAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("SentTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SourceAddress") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("SequenceNumber"); + + b.HasIndex("EnqueueTime"); + + b.HasIndex("ExpirationTime"); + + b.HasIndex("OutboxId", "SequenceNumber") + .IsUnique(); + + b.HasIndex("InboxMessageId", "InboxConsumerId", "SequenceNumber") + .IsUnique(); + + b.ToTable("OutboxMessage"); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxState", b => + { + b.Property("OutboxId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Created") + .HasColumnType("timestamp with time zone"); + + b.Property("Delivered") + .HasColumnType("timestamp with time zone"); + + b.Property("LastSequenceNumber") + .HasColumnType("bigint"); + + b.Property("LockId") + .HasColumnType("uuid"); + + b.Property("RowVersion") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("bytea"); + + b.HasKey("OutboxId"); + + b.HasIndex("Created"); + + b.ToTable("OutboxState"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.PlayList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LargePictureName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LifeCycleStatus") + .HasColumnType("integer"); + + b.Property("MediumPictureName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OriginalPictureName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("SmallPictureName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("PlayLists"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PlayListId") + .HasColumnType("uuid"); + + b.Property("Position") + .HasColumnType("integer"); + + b.Property("TrackId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("PlayListId"); + + b.HasIndex("TrackId"); + + b.ToTable("PlayListHasTrack"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.Track", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AudioFolderName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("AudioTranscodeProcessingStatus") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LargePictureName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("LastRetryAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LifeCycleStatus") + .HasColumnType("integer"); + + b.Property("MediumPictureName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("NormalizedTitle") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OriginalAudioName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("OriginalPictureName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("PicturesProcessingStatus") + .HasColumnType("integer"); + + b.Property("RetryCount") + .HasColumnType("integer"); + + b.Property("SmallPictureName") + .HasMaxLength(64) + .HasColumnType("character varying(64)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("Tracks"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.Upload", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Bucket") + .IsRequired() + .HasColumnType("text"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Upload"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Bucket") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("ContentType") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpectedSizeBytes") + .HasColumnType("bigint"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("character varying(512)"); + + b.Property("ObjectName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("Purpose") + .HasColumnType("integer"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UploadIntents"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.User", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FirstName") + .HasMaxLength(48) + .HasColumnType("character varying(48)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(48) + .HasColumnType("character varying(48)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(48) + .HasColumnType("character varying(48)"); + + b.Property("ProfilePictureUrl") + .HasMaxLength(2048) + .HasColumnType("character varying(2048)"); + + b.Property("SecondName") + .HasMaxLength(48) + .HasColumnType("character varying(48)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("TrackId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("TrackId"); + + b.HasIndex("UserId"); + + b.ToTable("UserHasTrack"); + }); + + modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b => + { + b.HasOne("MassTransit.EntityFrameworkCoreIntegration.OutboxState", null) + .WithMany() + .HasForeignKey("OutboxId"); + + b.HasOne("MassTransit.EntityFrameworkCoreIntegration.InboxState", null) + .WithMany() + .HasForeignKey("InboxMessageId", "InboxConsumerId") + .HasPrincipalKey("MessageId", "ConsumerId"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.PlayList", b => + { + b.HasOne("Musify.Domain.Entities.User", "User") + .WithMany("PlayLists") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b => + { + b.HasOne("Musify.Domain.Entities.PlayList", "PlayList") + .WithMany("PlayListTracks") + .HasForeignKey("PlayListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Musify.Domain.Entities.Track", "Track") + .WithMany("PlayListTracks") + .HasForeignKey("TrackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlayList"); + + b.Navigation("Track"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b => + { + b.HasOne("Musify.Domain.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b => + { + b.HasOne("Musify.Domain.Entities.Track", "Track") + .WithMany("UserTracks") + .HasForeignKey("TrackId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Musify.Domain.Entities.User", "User") + .WithMany("UserTracks") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Track"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.PlayList", b => + { + b.Navigation("PlayListTracks"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.Track", b => + { + b.Navigation("PlayListTracks"); + + b.Navigation("UserTracks"); + }); + + modelBuilder.Entity("Musify.Domain.Entities.User", b => + { + b.Navigation("PlayLists"); + + b.Navigation("UserTracks"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.cs b/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.cs new file mode 100644 index 0000000..540250e --- /dev/null +++ b/Infrastructure/Persistence/Migrations/20260601195757_RenameTimestampsAndAudit.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Musify.Infrastructure.Persistence.Migrations +{ + /// + public partial class RenameTimestampsAndAudit : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "UpdatedDate", + table: "Tracks", + newName: "UpdatedAt"); + + migrationBuilder.RenameColumn( + name: "CreatedDate", + table: "Tracks", + newName: "CreatedAt"); + + migrationBuilder.RenameColumn( + name: "UpdatedDate", + table: "PlayLists", + newName: "UpdatedAt"); + + migrationBuilder.RenameColumn( + name: "CreatedDate", + table: "PlayLists", + newName: "CreatedAt"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "UpdatedAt", + table: "Tracks", + newName: "UpdatedDate"); + + migrationBuilder.RenameColumn( + name: "CreatedAt", + table: "Tracks", + newName: "CreatedDate"); + + migrationBuilder.RenameColumn( + name: "UpdatedAt", + table: "PlayLists", + newName: "UpdatedDate"); + + migrationBuilder.RenameColumn( + name: "CreatedAt", + table: "PlayLists", + newName: "CreatedDate"); + } + } +} diff --git a/Infrastructure/Persistence/Migrations/DatabaseModelSnapshot.cs b/Infrastructure/Persistence/Migrations/DatabaseModelSnapshot.cs index 2192161..b6f5653 100644 --- a/Infrastructure/Persistence/Migrations/DatabaseModelSnapshot.cs +++ b/Infrastructure/Persistence/Migrations/DatabaseModelSnapshot.cs @@ -196,7 +196,7 @@ namespace Musify.Infrastructure.Persistence.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("CreatedDate") + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); b.Property("Description") @@ -237,7 +237,7 @@ namespace Musify.Infrastructure.Persistence.Migrations .HasMaxLength(64) .HasColumnType("character varying(64)"); - b.Property("UpdatedDate") + b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); b.Property("UserId") @@ -290,7 +290,7 @@ namespace Musify.Infrastructure.Persistence.Migrations b.Property("AudioTranscodeProcessingStatus") .HasColumnType("integer"); - b.Property("CreatedDate") + b.Property("CreatedAt") .HasColumnType("timestamp with time zone"); b.Property("LargePictureName") @@ -337,7 +337,7 @@ namespace Musify.Infrastructure.Persistence.Migrations .HasMaxLength(50) .HasColumnType("character varying(50)"); - b.Property("UpdatedDate") + b.Property("UpdatedAt") .HasColumnType("timestamp with time zone"); b.HasKey("Id");