Design Prot Merge #1

Merged
NotS1mp merged 217 commits from design-prot into master 2026-09-21 15:48:16 +00:00
9 changed files with 877 additions and 33 deletions
Showing only changes of commit 3f4f248221 - Show all commits
@@ -120,8 +120,8 @@ namespace Musify.Application.PlayLists
ExternalId = request.VideoId, ExternalId = request.VideoId,
DownloadRequested = true, DownloadRequested = true,
Duration = request.DurationSeconds, Duration = request.DurationSeconds,
OriginalPictureName = string.Empty, OriginalPictureName = null,
OriginalAudioName = string.Empty, OriginalAudioName = null,
SmallPictureName = trackConfiguration.Routes.PresetSmallPicture, SmallPictureName = trackConfiguration.Routes.PresetSmallPicture,
MediumPictureName = trackConfiguration.Routes.PresetMediumPicture, MediumPictureName = trackConfiguration.Routes.PresetMediumPicture,
LargePictureName = trackConfiguration.Routes.PresetLargePicture, LargePictureName = trackConfiguration.Routes.PresetLargePicture,
@@ -6,9 +6,9 @@ namespace Musify.Application.Tracks.Responses
public record TrackApplicationResponse( public record TrackApplicationResponse(
Guid Id, Guid Id,
string Title, string Title,
string Artist, string? Artist,
TrackSource Source, TrackSource Source,
string ExternalId, string? ExternalId,
ProcessingStatus AudioStatus, ProcessingStatus AudioStatus,
int Duration, int Duration,
int ListensCount, int ListensCount,
@@ -91,8 +91,8 @@ namespace Musify.Application.YouTube
ExternalId = videoId, ExternalId = videoId,
DownloadRequested = false, DownloadRequested = false,
Duration = song.DurationSeconds, Duration = song.DurationSeconds,
OriginalPictureName = string.Empty, OriginalPictureName = null,
OriginalAudioName = string.Empty, OriginalAudioName = null,
SmallPictureName = trackConfiguration.Routes.PresetSmallPicture, SmallPictureName = trackConfiguration.Routes.PresetSmallPicture,
MediumPictureName = trackConfiguration.Routes.PresetMediumPicture, MediumPictureName = trackConfiguration.Routes.PresetMediumPicture,
LargePictureName = trackConfiguration.Routes.PresetLargePicture, LargePictureName = trackConfiguration.Routes.PresetLargePicture,
+5 -9
View File
@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using Musify.Domain.Abstractions; using Musify.Domain.Abstractions;
@@ -23,23 +23,20 @@ namespace Musify.Domain.Entities
[Required] [Required]
public int Duration { get; set; } public int Duration { get; set; }
[Required]
[MaxLength(200)] [MaxLength(200)]
public string Artist { get; set; } = string.Empty; public string? Artist { get; set; }
[Required] [Required]
public TrackSource Source { get; set; } = TrackSource.Local; public TrackSource Source { get; set; } = TrackSource.Local;
[Required]
[MaxLength(16)] [MaxLength(16)]
public string ExternalId { get; set; } = string.Empty; public string? ExternalId { get; set; }
[Required] [Required]
public bool DownloadRequested { get; set; } = false; public bool DownloadRequested { get; set; } = false;
[Required]
[MaxLength(64)] [MaxLength(64)]
public required string OriginalPictureName { get; set; } public string? OriginalPictureName { get; set; }
[MaxLength(64)] [MaxLength(64)]
public string? SmallPictureName { get; set; } public string? SmallPictureName { get; set; }
@@ -50,9 +47,8 @@ namespace Musify.Domain.Entities
[MaxLength(64)] [MaxLength(64)]
public string? LargePictureName { get; set; } public string? LargePictureName { get; set; }
[Required]
[MaxLength(64)] [MaxLength(64)]
public required string OriginalAudioName { get; set; } public string? OriginalAudioName { get; set; }
[MaxLength(64)] [MaxLength(64)]
public string? AudioFolderName { get; set; } public string? AudioFolderName { get; set; }
@@ -2,8 +2,8 @@ namespace Musify.Infrastructure.MassTransit.Logs
{ {
public record UpdateTrackPictureLog( public record UpdateTrackPictureLog(
Guid TrackId, Guid TrackId,
string PreviousOriginalPictureKey, string? PreviousOriginalPictureKey,
string? PreviousSmallPictureKey, string? PreviousSmallPictureKey,
string? PreviousMediumPictureKey, string? PreviousMediumPictureKey,
string? PreviousLargePictureKey); string? PreviousLargePictureKey);
} }
@@ -41,12 +41,15 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
{ {
var bucket = storageConfiguration.Bucket; var bucket = storageConfiguration.Bucket;
routingSlipBuilder.AddActivity( if (!string.IsNullOrEmpty(track.OriginalPictureName))
ActivityNames.RemoveTrackOriginalPicture, {
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), routingSlipBuilder.AddActivity(
new RemoveFileFromBucketArguments( ActivityNames.RemoveTrackOriginalPicture,
bucket, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
trackConfiguration.Routes.BuildOriginalPicturePath(userId, track.OriginalPictureName))); new RemoveFileFromBucketArguments(
bucket,
trackConfiguration.Routes.BuildOriginalPicturePath(userId, track.OriginalPictureName)));
}
if (track.IsPicturesProcessed) if (track.IsPicturesProcessed)
{ {
@@ -72,12 +75,15 @@ namespace Musify.Infrastructure.MassTransit.RoutingSlip.Builders
trackConfiguration.Routes.BuildLargePicturePath(track.LargePictureName))); trackConfiguration.Routes.BuildLargePicturePath(track.LargePictureName)));
} }
routingSlipBuilder.AddActivity( if (!string.IsNullOrEmpty(track.OriginalAudioName))
ActivityNames.RemoveTrackOriginalAudio, {
EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName), routingSlipBuilder.AddActivity(
new RemoveFileFromBucketArguments( ActivityNames.RemoveTrackOriginalAudio,
bucket, EndpointHelper.BuildExecuteActivityUri(RemoveFileFromBucketActivity.ExecuteEndpointName),
trackConfiguration.Routes.BuildOriginalAudioPath(userId, track.OriginalAudioName))); new RemoveFileFromBucketArguments(
bucket,
trackConfiguration.Routes.BuildOriginalAudioPath(userId, track.OriginalAudioName)));
}
if (track.IsAudioProcessed) if (track.IsAudioProcessed)
{ {
@@ -32,8 +32,7 @@ namespace Musify.Infrastructure.Persistence
modelBuilder.Entity<Track>() modelBuilder.Entity<Track>()
.HasIndex(track => new { track.Source, track.ExternalId }) .HasIndex(track => new { track.Source, track.ExternalId })
.IsUnique() .IsUnique();
.HasFilter("\"ExternalId\" <> ''");
var playListProcessing = modelBuilder.Entity<PlayListProcessingState>(); var playListProcessing = modelBuilder.Entity<PlayListProcessingState>();
playListProcessing.HasKey(state => state.CorrelationId); playListProcessing.HasKey(state => state.CorrelationId);
@@ -0,0 +1,711 @@
// <auto-generated />
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("20260716214442_MakeTrackMediaAndExternalIdNullable")]
partial class MakeTrackMediaAndExternalIdNullable
{
/// <inheritdoc />
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<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime?>("Consumed")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("ConsumerId")
.HasColumnType("uuid");
b.Property<DateTime?>("Delivered")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("timestamp with time zone");
b.Property<long?>("LastSequenceNumber")
.HasColumnType("bigint");
b.Property<Guid>("LockId")
.HasColumnType("uuid");
b.Property<Guid>("MessageId")
.HasColumnType("uuid");
b.Property<int>("ReceiveCount")
.HasColumnType("integer");
b.Property<DateTime>("Received")
.HasColumnType("timestamp with time zone");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("bytea");
b.HasKey("Id");
b.HasIndex("Delivered");
b.ToTable("InboxState");
});
modelBuilder.Entity("MassTransit.EntityFrameworkCoreIntegration.OutboxMessage", b =>
{
b.Property<long>("SequenceNumber")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("SequenceNumber"));
b.Property<string>("Body")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ContentType")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<Guid?>("ConversationId")
.HasColumnType("uuid");
b.Property<Guid?>("CorrelationId")
.HasColumnType("uuid");
b.Property<string>("DestinationAddress")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime?>("EnqueueTime")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("ExpirationTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("FaultAddress")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("Headers")
.HasColumnType("text");
b.Property<Guid?>("InboxConsumerId")
.HasColumnType("uuid");
b.Property<Guid?>("InboxMessageId")
.HasColumnType("uuid");
b.Property<Guid?>("InitiatorId")
.HasColumnType("uuid");
b.Property<Guid>("MessageId")
.HasColumnType("uuid");
b.Property<string>("MessageType")
.IsRequired()
.HasColumnType("text");
b.Property<Guid?>("OutboxId")
.HasColumnType("uuid");
b.Property<string>("Properties")
.HasColumnType("text");
b.Property<Guid?>("RequestId")
.HasColumnType("uuid");
b.Property<string>("ResponseAddress")
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<DateTime>("SentTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("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<Guid>("OutboxId")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("Created")
.HasColumnType("timestamp with time zone");
b.Property<DateTime?>("Delivered")
.HasColumnType("timestamp with time zone");
b.Property<long?>("LastSequenceNumber")
.HasColumnType("bigint");
b.Property<Guid>("LockId")
.HasColumnType("uuid");
b.Property<byte[]>("RowVersion")
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate()
.HasColumnType("bytea");
b.HasKey("OutboxId");
b.HasIndex("Created");
b.ToTable("OutboxState");
});
modelBuilder.Entity("Musify.Domain.Entities.ListeningHistory", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("ListenedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("TrackId")
.HasColumnType("uuid");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("TrackId");
b.HasIndex("UserId");
b.ToTable("ListeningHistory");
});
modelBuilder.Entity("Musify.Domain.Entities.PlayList", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("character varying(256)");
b.Property<string>("LargePictureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("LifeCycleStatus")
.HasColumnType("integer");
b.Property<string>("MediumPictureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("OriginalPictureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("SmallPictureName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("PlayLists");
});
modelBuilder.Entity("Musify.Domain.Entities.PlayListHasTrack", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("AddedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("PlayListId")
.HasColumnType("uuid");
b.Property<int>("Position")
.HasColumnType("integer");
b.Property<Guid>("TrackId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PlayListId");
b.HasIndex("TrackId");
b.ToTable("PlayListHasTrack");
});
modelBuilder.Entity("Musify.Domain.Entities.Track", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Artist")
.HasMaxLength(200)
.HasColumnType("character varying(200)");
b.Property<string>("AudioFolderName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("AudioTranscodeProcessingStatus")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("DownloadRequested")
.HasColumnType("boolean");
b.Property<int>("Duration")
.HasColumnType("integer");
b.Property<string>("ExternalId")
.HasMaxLength(16)
.HasColumnType("character varying(16)");
b.Property<string>("LargePictureName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<DateTime?>("LastRetryAt")
.HasColumnType("timestamp with time zone");
b.Property<int>("LifeCycleStatus")
.HasColumnType("integer");
b.Property<string>("MediumPictureName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("NormalizedTitle")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<string>("OriginalAudioName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("OriginalPictureName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("PicturesProcessingStatus")
.HasColumnType("integer");
b.Property<int>("RetryCount")
.HasColumnType("integer");
b.Property<string>("SmallPictureName")
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<int>("Source")
.HasColumnType("integer");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("Source", "ExternalId")
.IsUnique();
b.ToTable("Tracks");
});
modelBuilder.Entity("Musify.Domain.Entities.Upload", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Bucket")
.IsRequired()
.HasColumnType("text");
b.Property<string>("ContentType")
.IsRequired()
.HasColumnType("text");
b.Property<DateTime>("CreatedTime")
.HasColumnType("timestamp with time zone");
b.Property<string>("Key")
.IsRequired()
.HasColumnType("text");
b.Property<int>("State")
.HasColumnType("integer");
b.HasKey("Id");
b.ToTable("Upload");
});
modelBuilder.Entity("Musify.Domain.Entities.UploadIntent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Bucket")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<string>("ContentType")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<long?>("ExpectedSizeBytes")
.HasColumnType("bigint");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(512)
.HasColumnType("character varying(512)");
b.Property<string>("ObjectName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)");
b.Property<int>("Purpose")
.HasColumnType("integer");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("UploadIntents");
});
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
{
b.Property<long>("Id")
.HasColumnType("bigint");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("FirstName")
.HasMaxLength(48)
.HasColumnType("character varying(48)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(48)
.HasColumnType("character varying(48)");
b.Property<string>("NormalizedName")
.IsRequired()
.HasMaxLength(48)
.HasColumnType("character varying(48)");
b.Property<string>("ProfilePictureUrl")
.HasMaxLength(2048)
.HasColumnType("character varying(2048)");
b.Property<string>("SecondName")
.HasMaxLength(48)
.HasColumnType("character varying(48)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("User");
});
modelBuilder.Entity("Musify.Domain.Entities.UserHasTrack", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("TrackId")
.HasColumnType("uuid");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("TrackId");
b.HasIndex("UserId");
b.ToTable("UserHasTrack");
});
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.PlayListProcessingState", b =>
{
b.Property<Guid>("CorrelationId")
.HasColumnType("uuid");
b.Property<string>("Bucket")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("CurrentState")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("PictureKey")
.HasColumnType("text");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("CorrelationId");
b.ToTable("PlayListProcessingState");
});
modelBuilder.Entity("Musify.Infrastructure.MassTransit.Sagas.TrackProcessingState", b =>
{
b.Property<Guid>("CorrelationId")
.HasColumnType("uuid");
b.Property<string>("AudioKey")
.HasColumnType("text");
b.Property<bool>("AudioProcessed")
.HasColumnType("boolean");
b.Property<string>("Bucket")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("CurrentState")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)");
b.Property<string>("PictureKey")
.HasColumnType("text");
b.Property<bool>("PictureProcessed")
.HasColumnType("boolean");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
b.HasKey("CorrelationId");
b.ToTable("TrackProcessingState");
});
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.ListeningHistory", b =>
{
b.HasOne("Musify.Domain.Entities.Track", "Track")
.WithMany("ListeningHistories")
.HasForeignKey("TrackId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Musify.Domain.Entities.User", "User")
.WithMany("ListeningHistories")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Track");
b.Navigation("User");
});
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("ListeningHistories");
b.Navigation("PlayListTracks");
b.Navigation("UserTracks");
});
modelBuilder.Entity("Musify.Domain.Entities.User", b =>
{
b.Navigation("ListeningHistories");
b.Navigation("PlayLists");
b.Navigation("UserTracks");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,132 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Musify.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class MakeTrackMediaAndExternalIdNullable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Tracks_Source_ExternalId",
table: "Tracks");
migrationBuilder.AlterColumn<string>(
name: "OriginalPictureName",
table: "Tracks",
type: "character varying(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(64)",
oldMaxLength: 64);
migrationBuilder.AlterColumn<string>(
name: "OriginalAudioName",
table: "Tracks",
type: "character varying(64)",
maxLength: 64,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(64)",
oldMaxLength: 64);
migrationBuilder.AlterColumn<string>(
name: "ExternalId",
table: "Tracks",
type: "character varying(16)",
maxLength: 16,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(16)",
oldMaxLength: 16);
migrationBuilder.AlterColumn<string>(
name: "Artist",
table: "Tracks",
type: "character varying(200)",
maxLength: 200,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(200)",
oldMaxLength: 200);
migrationBuilder.Sql("UPDATE \"Tracks\" SET \"ExternalId\" = NULL WHERE \"ExternalId\" = '';");
migrationBuilder.Sql("UPDATE \"Tracks\" SET \"Artist\" = NULL WHERE \"Artist\" = '';");
migrationBuilder.Sql("UPDATE \"Tracks\" SET \"OriginalPictureName\" = NULL WHERE \"OriginalPictureName\" = '';");
migrationBuilder.Sql("UPDATE \"Tracks\" SET \"OriginalAudioName\" = NULL WHERE \"OriginalAudioName\" = '';");
migrationBuilder.CreateIndex(
name: "IX_Tracks_Source_ExternalId",
table: "Tracks",
columns: new[] { "Source", "ExternalId" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Tracks_Source_ExternalId",
table: "Tracks");
migrationBuilder.AlterColumn<string>(
name: "OriginalPictureName",
table: "Tracks",
type: "character varying(64)",
maxLength: 64,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(64)",
oldMaxLength: 64,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "OriginalAudioName",
table: "Tracks",
type: "character varying(64)",
maxLength: 64,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(64)",
oldMaxLength: 64,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "ExternalId",
table: "Tracks",
type: "character varying(16)",
maxLength: 16,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(16)",
oldMaxLength: 16,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Artist",
table: "Tracks",
type: "character varying(200)",
maxLength: 200,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(200)",
oldMaxLength: 200,
oldNullable: true);
migrationBuilder.CreateIndex(
name: "IX_Tracks_Source_ExternalId",
table: "Tracks",
columns: new[] { "Source", "ExternalId" },
unique: true,
filter: "\"ExternalId\" <> ''");
}
}
}