diff --git a/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.Designer.cs b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.Designer.cs
new file mode 100644
index 0000000..c22cf8d
--- /dev/null
+++ b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.Designer.cs
@@ -0,0 +1,446 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TibiaStalker.Infrastructure.Persistence;
+
+#nullable disable
+
+namespace TibiaStalker.Infrastructure.Persistence.Migrations
+{
+ [DbContext(typeof(TibiaStalkerDbContext))]
+ [Migration("20240715151206_Change_Indexes_on_OnlineCharacter")]
+ partial class ChangeIndexesonOnlineCharacter
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasDefaultSchema("public")
+ .HasAnnotation("ProductVersion", "7.0.2")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.Character", b =>
+ {
+ b.Property("CharacterId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("character_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CharacterId"));
+
+ b.Property("DeleteApproachNumber")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasDefaultValue(0)
+ .HasColumnName("delete_approach_number");
+
+ b.Property("FoundInScan1")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false)
+ .HasColumnName("found_in_scan1");
+
+ b.Property("FoundInScan2")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false)
+ .HasColumnName("found_in_scan2");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("TradedDate")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("date")
+ .HasDefaultValue(new DateOnly(2001, 1, 1))
+ .HasColumnName("traded_date");
+
+ b.Property("VerifiedDate")
+ .IsRequired()
+ .ValueGeneratedOnAdd()
+ .HasColumnType("date")
+ .HasDefaultValue(new DateOnly(2001, 1, 1))
+ .HasColumnName("verified_date");
+
+ b.Property("WorldId")
+ .HasColumnType("smallint")
+ .HasColumnName("world_id");
+
+ b.HasKey("CharacterId")
+ .HasName("pk_characters");
+
+ b.HasIndex("FoundInScan1")
+ .HasDatabaseName("ix_characters_found_in_scan1");
+
+ b.HasIndex("FoundInScan2")
+ .HasDatabaseName("ix_characters_found_in_scan2");
+
+ b.HasIndex("Name")
+ .HasDatabaseName("ix_characters_name");
+
+ b.HasIndex("TradedDate")
+ .HasDatabaseName("ix_characters_traded_date");
+
+ b.HasIndex("VerifiedDate")
+ .HasDatabaseName("ix_characters_verified_date");
+
+ b.HasIndex("WorldId")
+ .HasDatabaseName("ix_characters_world_id");
+
+ b.HasIndex("FoundInScan1", "FoundInScan2")
+ .HasDatabaseName("ix_characters_scan1_scan2");
+
+ b.HasIndex("FoundInScan2", "FoundInScan1")
+ .HasDatabaseName("ix_characters_scan2_scan1");
+
+ b.ToTable("characters", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.CharacterAction", b =>
+ {
+ b.Property("CharacterActionId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("character_action_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CharacterActionId"));
+
+ b.Property("CharacterName")
+ .IsRequired()
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("character_name");
+
+ b.Property("IsOnline")
+ .HasColumnType("boolean")
+ .HasColumnName("is_online");
+
+ b.Property("LogoutOrLoginDate")
+ .HasColumnType("date")
+ .HasColumnName("logout_or_login_date");
+
+ b.Property("WorldId")
+ .HasColumnType("smallint")
+ .HasColumnName("world_id");
+
+ b.Property("WorldScanId")
+ .HasColumnType("integer")
+ .HasColumnName("world_scan_id");
+
+ b.HasKey("CharacterActionId")
+ .HasName("pk_character_actions");
+
+ b.HasIndex("CharacterName")
+ .HasDatabaseName("ix_character_actions_character_name");
+
+ b.HasIndex("IsOnline")
+ .HasDatabaseName("ix_character_actions_is_online");
+
+ b.HasIndex("LogoutOrLoginDate")
+ .HasDatabaseName("ix_character_actions_logout_or_login_date");
+
+ b.HasIndex("WorldId")
+ .HasDatabaseName("ix_character_actions_world_id");
+
+ b.HasIndex("WorldScanId")
+ .HasDatabaseName("ix_character_actions_world_scan_id");
+
+ b.HasIndex("IsOnline", "CharacterName")
+ .HasDatabaseName("ix_character_actions_is_online_character_name");
+
+ b.ToTable("character_actions", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.CharacterCorrelation", b =>
+ {
+ b.Property("CorrelationId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasColumnName("correlation_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("CorrelationId"));
+
+ b.Property("CreateDate")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("date")
+ .HasDefaultValue(new DateOnly(2022, 12, 6))
+ .HasColumnName("create_date");
+
+ b.Property("LastMatchDate")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("date")
+ .HasDefaultValue(new DateOnly(2022, 12, 6))
+ .HasColumnName("last_match_date");
+
+ b.Property("LoginCharacterId")
+ .HasColumnType("integer")
+ .HasColumnName("login_character_id");
+
+ b.Property("LogoutCharacterId")
+ .HasColumnType("integer")
+ .HasColumnName("logout_character_id");
+
+ b.Property("NumberOfMatches")
+ .HasColumnType("smallint")
+ .HasColumnName("number_of_matches");
+
+ b.HasKey("CorrelationId")
+ .HasName("pk_character_correlations");
+
+ b.HasIndex("LoginCharacterId")
+ .HasDatabaseName("ix_character_correlations_login_character_id");
+
+ b.HasIndex("LogoutCharacterId")
+ .HasDatabaseName("ix_character_correlations_logout_character_id");
+
+ b.HasIndex("NumberOfMatches")
+ .HasDatabaseName("ix_character_correlations_number_of_matches");
+
+ b.HasIndex("LoginCharacterId", "LogoutCharacterId")
+ .HasDatabaseName("ix_correlations_login_character_id_logout_character_id");
+
+ b.HasIndex("LogoutCharacterId", "LoginCharacterId")
+ .HasDatabaseName("ix_correlations_logout_character_id_login_character_id");
+
+ b.HasIndex("NumberOfMatches", "LastMatchDate")
+ .HasDatabaseName("ix_correlations_number_matches_last_match_date");
+
+ b.ToTable("character_correlations", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.OnlineCharacter", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("OnlineDateTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("online_date_time");
+
+ b.Property("WorldName")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("world_name");
+
+ b.HasKey("Name", "OnlineDateTime")
+ .HasName("pk_online_characters");
+
+ b.HasIndex("WorldName")
+ .HasDatabaseName("ix_online_characters_world_name");
+
+ b.ToTable("online_characters", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.TrackedCharacter", b =>
+ {
+ b.Property("Name")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("name");
+
+ b.Property("ConnectionId")
+ .HasMaxLength(100)
+ .HasColumnType("character varying(100)")
+ .HasColumnName("connection_id");
+
+ b.Property("StartTrackDateTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("start_track_date_time");
+
+ b.Property("WorldName")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("world_name");
+
+ b.HasKey("Name", "ConnectionId")
+ .HasName("pk_tracked_characters");
+
+ b.HasIndex("Name")
+ .HasDatabaseName("ix_tracked_characters_name");
+
+ b.HasIndex("WorldName")
+ .HasDatabaseName("ix_tracked_characters_world_name");
+
+ b.ToTable("tracked_characters", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.World", b =>
+ {
+ b.Property("WorldId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasColumnName("world_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorldId"));
+
+ b.Property("IsAvailable")
+ .HasColumnType("boolean")
+ .HasColumnName("is_available");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(20)
+ .HasColumnType("character varying(20)")
+ .HasColumnName("name");
+
+ b.Property("Url")
+ .IsRequired()
+ .HasMaxLength(200)
+ .HasColumnType("character varying(200)")
+ .HasColumnName("url");
+
+ b.HasKey("WorldId")
+ .HasName("pk_worlds");
+
+ b.ToTable("worlds", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.WorldScan", b =>
+ {
+ b.Property("WorldScanId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer")
+ .HasColumnName("world_scan_id");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("WorldScanId"));
+
+ b.Property("CharactersOnline")
+ .IsRequired()
+ .HasColumnType("text")
+ .HasColumnName("characters_online");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("boolean")
+ .HasDefaultValue(false)
+ .HasColumnName("is_deleted");
+
+ b.Property("ScanCreateDateTime")
+ .HasColumnType("timestamp with time zone")
+ .HasColumnName("scan_create_date_time");
+
+ b.Property("WorldId")
+ .HasColumnType("smallint")
+ .HasColumnName("world_id");
+
+ b.HasKey("WorldScanId")
+ .HasName("pk_world_scans");
+
+ b.HasIndex("IsDeleted")
+ .HasDatabaseName("ix_world_scans_is_deleted");
+
+ b.HasIndex("ScanCreateDateTime")
+ .HasDatabaseName("ix_world_scans_scan_create_date_time");
+
+ b.HasIndex("WorldId")
+ .HasDatabaseName("ix_world_scans_world_id");
+
+ b.HasIndex("WorldId", "IsDeleted")
+ .HasDatabaseName("ix_world_scan_id_world_id_is_deleted");
+
+ b.HasIndex("WorldId", "IsDeleted", "ScanCreateDateTime")
+ .HasDatabaseName("ix_world_scan_world_id_is_deleted_scan_date_time");
+
+ b.ToTable("world_scans", "public");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.Character", b =>
+ {
+ b.HasOne("TibiaStalker.Domain.Entities.World", "World")
+ .WithMany("Characters")
+ .HasForeignKey("WorldId")
+ .OnDelete(DeleteBehavior.NoAction)
+ .IsRequired()
+ .HasConstraintName("fk_characters_worlds_world_id");
+
+ b.Navigation("World");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.CharacterAction", b =>
+ {
+ b.HasOne("TibiaStalker.Domain.Entities.World", "World")
+ .WithMany("CharacterLogoutOrLogins")
+ .HasForeignKey("WorldId")
+ .OnDelete(DeleteBehavior.NoAction)
+ .IsRequired()
+ .HasConstraintName("fk_character_actions_worlds_world_id");
+
+ b.HasOne("TibiaStalker.Domain.Entities.WorldScan", "WorldScan")
+ .WithMany()
+ .HasForeignKey("WorldScanId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_character_actions_world_scans_world_scan_id");
+
+ b.Navigation("World");
+
+ b.Navigation("WorldScan");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.CharacterCorrelation", b =>
+ {
+ b.HasOne("TibiaStalker.Domain.Entities.Character", "LoginCharacter")
+ .WithMany("LoginCharacterCorrelations")
+ .HasForeignKey("LoginCharacterId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_character_correlations_characters_login_character_id");
+
+ b.HasOne("TibiaStalker.Domain.Entities.Character", "LogoutCharacter")
+ .WithMany("LogoutCharacterCorrelations")
+ .HasForeignKey("LogoutCharacterId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired()
+ .HasConstraintName("fk_character_correlations_characters_character_id");
+
+ b.Navigation("LoginCharacter");
+
+ b.Navigation("LogoutCharacter");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.WorldScan", b =>
+ {
+ b.HasOne("TibiaStalker.Domain.Entities.World", "World")
+ .WithMany("WorldScans")
+ .HasForeignKey("WorldId")
+ .OnDelete(DeleteBehavior.NoAction)
+ .IsRequired()
+ .HasConstraintName("fk_world_scans_worlds_world_id");
+
+ b.Navigation("World");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.Character", b =>
+ {
+ b.Navigation("LoginCharacterCorrelations");
+
+ b.Navigation("LogoutCharacterCorrelations");
+ });
+
+ modelBuilder.Entity("TibiaStalker.Domain.Entities.World", b =>
+ {
+ b.Navigation("CharacterLogoutOrLogins");
+
+ b.Navigation("Characters");
+
+ b.Navigation("WorldScans");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.cs b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.cs
new file mode 100644
index 0000000..2a35848
--- /dev/null
+++ b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/20240715151206_Change_Indexes_on_OnlineCharacter.cs
@@ -0,0 +1,51 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace TibiaStalker.Infrastructure.Persistence.Migrations
+{
+ ///
+ public partial class ChangeIndexesonOnlineCharacter : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropPrimaryKey(
+ name: "pk_online_characters",
+ schema: "public",
+ table: "online_characters");
+
+ migrationBuilder.DropIndex(
+ name: "ix_online_characters_name",
+ schema: "public",
+ table: "online_characters");
+
+ migrationBuilder.AddPrimaryKey(
+ name: "pk_online_characters",
+ schema: "public",
+ table: "online_characters",
+ columns: new[] { "name", "online_date_time" });
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropPrimaryKey(
+ name: "pk_online_characters",
+ schema: "public",
+ table: "online_characters");
+
+ migrationBuilder.AddPrimaryKey(
+ name: "pk_online_characters",
+ schema: "public",
+ table: "online_characters",
+ column: "name");
+
+ migrationBuilder.CreateIndex(
+ name: "ix_online_characters_name",
+ schema: "public",
+ table: "online_characters",
+ column: "name");
+ }
+ }
+}
diff --git a/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/TibiaStalkerDbContextModelSnapshot.cs b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/TibiaStalkerDbContextModelSnapshot.cs
index 94612de..cd965ff 100644
--- a/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/TibiaStalkerDbContextModelSnapshot.cs
+++ b/API/src/TibiaStalker.Infrastructure/Persistence/Migrations/TibiaStalkerDbContextModelSnapshot.cs
@@ -233,12 +233,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.HasColumnType("character varying(20)")
.HasColumnName("world_name");
- b.HasKey("Name")
+ b.HasKey("Name", "OnlineDateTime")
.HasName("pk_online_characters");
- b.HasIndex("Name")
- .HasDatabaseName("ix_online_characters_name");
-
b.HasIndex("WorldName")
.HasDatabaseName("ix_online_characters_world_name");
diff --git a/API/src/TibiaStalker.Infrastructure/Persistence/TibiaStalkerDbContext.cs b/API/src/TibiaStalker.Infrastructure/Persistence/TibiaStalkerDbContext.cs
index 7a3ae09..04acd3c 100644
--- a/API/src/TibiaStalker.Infrastructure/Persistence/TibiaStalkerDbContext.cs
+++ b/API/src/TibiaStalker.Infrastructure/Persistence/TibiaStalkerDbContext.cs
@@ -251,9 +251,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity(e =>
{
- e.HasIndex(oc => oc.Name);
e.HasIndex(oc => oc.WorldName);
- e.HasKey(oc => oc.Name);
+ e.HasKey(oc => new {oc.Name, oc.OnlineDateTime});
e.Property(oc => oc.Name)
.HasMaxLength(100)