Add comprehensive documentation for PostgreSQL schema conversion
- Introduced DATABASE_SCHEMA_MISMATCH_REPORT.md to detail critical mismatches between SQL schema and C# code configurations, highlighting issues with naming conventions and potential runtime failures. - Created SCHEMA_COLUMN_CONVERSION_REFERENCE.md to provide a reference for column name conversions from PascalCase to snake_case across all tables. - Developed SCHEMA_CONVERSION_GUIDE.md outlining the conversion strategy for the SQL schema, including authoritative table mappings, column naming rules, and a validation checklist to ensure accuracy in the conversion process.
This commit is contained in:
@@ -126,6 +126,9 @@ public sealed class BaseItemRepository
|
|||||||
{
|
{
|
||||||
var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await using (context.ConfigureAwait(false))
|
await using (context.ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
var executionStrategy = context.Database.CreateExecutionStrategy();
|
||||||
|
await executionStrategy.ExecuteAsync(async () =>
|
||||||
{
|
{
|
||||||
var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false);
|
var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await using (transaction.ConfigureAwait(false))
|
await using (transaction.ConfigureAwait(false))
|
||||||
@@ -186,6 +189,7 @@ public sealed class BaseItemRepository
|
|||||||
await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
|
||||||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
}).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Npgsql.PostgresException ex) when (ex.SqlState == "40P01") // Deadlock detected
|
catch (Npgsql.PostgresException ex) when (ex.SqlState == "40P01") // Deadlock detected
|
||||||
@@ -1158,10 +1162,10 @@ public sealed class BaseItemRepository
|
|||||||
foreach (var provider in providersToUpsert)
|
foreach (var provider in providersToUpsert)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlAsync(
|
await context.Database.ExecuteSqlAsync(
|
||||||
$@"INSERT INTO library.""BaseItemProviders"" (""ItemId"", ""ProviderId"", ""ProviderValue"")
|
$@"INSERT INTO library.base_item_providers (item_id, provider_id, provider_value)
|
||||||
VALUES ({entity.Id}, {provider.ProviderId}, {provider.ProviderValue})
|
VALUES ({entity.Id}, {provider.ProviderId}, {provider.ProviderValue})
|
||||||
ON CONFLICT (""ItemId"", ""ProviderId"")
|
ON CONFLICT (item_id, provider_id)
|
||||||
DO UPDATE SET ""ProviderValue"" = EXCLUDED.""ProviderValue""",
|
DO UPDATE SET provider_value = EXCLUDED.provider_value",
|
||||||
cancellationToken)
|
cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -1202,14 +1206,14 @@ public sealed class BaseItemRepository
|
|||||||
if (tvExtras is not null)
|
if (tvExtras is not null)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlAsync(
|
await context.Database.ExecuteSqlAsync(
|
||||||
$@"INSERT INTO library.""BaseItemTvExtras"" (""ItemId"", ""SeriesId"", ""SeasonId"", ""SeriesName"", ""SeasonName"", ""SeriesPresentationUniqueKey"")
|
$@"INSERT INTO library.base_item_tv_extras (item_id, series_id, season_id, series_name, season_name, series_presentation_unique_key)
|
||||||
VALUES ({extItemId}, {tvExtras.SeriesId}, {tvExtras.SeasonId}, {tvExtras.SeriesName}, {tvExtras.SeasonName}, {tvExtras.SeriesPresentationUniqueKey})
|
VALUES ({extItemId}, {tvExtras.SeriesId}, {tvExtras.SeasonId}, {tvExtras.SeriesName}, {tvExtras.SeasonName}, {tvExtras.SeriesPresentationUniqueKey})
|
||||||
ON CONFLICT (""ItemId"") DO UPDATE SET
|
ON CONFLICT (item_id) DO UPDATE SET
|
||||||
""SeriesId"" = EXCLUDED.""SeriesId"",
|
series_id = EXCLUDED.series_id,
|
||||||
""SeasonId"" = EXCLUDED.""SeasonId"",
|
season_id = EXCLUDED.season_id,
|
||||||
""SeriesName"" = EXCLUDED.""SeriesName"",
|
series_name = EXCLUDED.series_name,
|
||||||
""SeasonName"" = EXCLUDED.""SeasonName"",
|
season_name = EXCLUDED.season_name,
|
||||||
""SeriesPresentationUniqueKey"" = EXCLUDED.""SeriesPresentationUniqueKey""",
|
series_presentation_unique_key = EXCLUDED.series_presentation_unique_key",
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1222,16 +1226,16 @@ public sealed class BaseItemRepository
|
|||||||
if (liveTvExtras is not null)
|
if (liveTvExtras is not null)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlAsync(
|
await context.Database.ExecuteSqlAsync(
|
||||||
$@"INSERT INTO library.""BaseItemLiveTvExtras"" (""ItemId"", ""StartDate"", ""EndDate"", ""EpisodeTitle"", ""ShowId"", ""ExternalSeriesId"", ""ExternalServiceId"", ""Audio"")
|
$@"INSERT INTO library.base_item_live_tv_extras (item_id, start_date, end_date, episode_title, show_id, external_series_id, external_service_id, audio)
|
||||||
VALUES ({extItemId}, {liveTvExtras.StartDate}, {liveTvExtras.EndDate}, {liveTvExtras.EpisodeTitle}, {liveTvExtras.ShowId}, {liveTvExtras.ExternalSeriesId}, {liveTvExtras.ExternalServiceId}, {(int?)liveTvExtras.Audio})
|
VALUES ({extItemId}, {liveTvExtras.StartDate}, {liveTvExtras.EndDate}, {liveTvExtras.EpisodeTitle}, {liveTvExtras.ShowId}, {liveTvExtras.ExternalSeriesId}, {liveTvExtras.ExternalServiceId}, {(int?)liveTvExtras.Audio})
|
||||||
ON CONFLICT (""ItemId"") DO UPDATE SET
|
ON CONFLICT (item_id) DO UPDATE SET
|
||||||
""StartDate"" = EXCLUDED.""StartDate"",
|
start_date = EXCLUDED.start_date,
|
||||||
""EndDate"" = EXCLUDED.""EndDate"",
|
end_date = EXCLUDED.end_date,
|
||||||
""EpisodeTitle"" = EXCLUDED.""EpisodeTitle"",
|
episode_title = EXCLUDED.episode_title,
|
||||||
""ShowId"" = EXCLUDED.""ShowId"",
|
show_id = EXCLUDED.show_id,
|
||||||
""ExternalSeriesId"" = EXCLUDED.""ExternalSeriesId"",
|
external_series_id = EXCLUDED.external_series_id,
|
||||||
""ExternalServiceId"" = EXCLUDED.""ExternalServiceId"",
|
external_service_id = EXCLUDED.external_service_id,
|
||||||
""Audio"" = EXCLUDED.""Audio""",
|
audio = EXCLUDED.audio",
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1244,14 +1248,14 @@ public sealed class BaseItemRepository
|
|||||||
if (audioExtras is not null)
|
if (audioExtras is not null)
|
||||||
{
|
{
|
||||||
await context.Database.ExecuteSqlAsync(
|
await context.Database.ExecuteSqlAsync(
|
||||||
$@"INSERT INTO library.""BaseItemAudioExtras"" (""ItemId"", ""Album"", ""Artists"", ""AlbumArtists"", ""LUFS"", ""NormalizationGain"")
|
$@"INSERT INTO library.base_item_audio_extras (item_id, album, artists, album_artists, lufs, normalization_gain)
|
||||||
VALUES ({extItemId}, {audioExtras.Album}, {audioExtras.Artists}, {audioExtras.AlbumArtists}, {audioExtras.LUFS}, {audioExtras.NormalizationGain})
|
VALUES ({extItemId}, {audioExtras.Album}, {audioExtras.Artists}, {audioExtras.AlbumArtists}, {audioExtras.LUFS}, {audioExtras.NormalizationGain})
|
||||||
ON CONFLICT (""ItemId"") DO UPDATE SET
|
ON CONFLICT (item_id) DO UPDATE SET
|
||||||
""Album"" = EXCLUDED.""Album"",
|
album = EXCLUDED.album,
|
||||||
""Artists"" = EXCLUDED.""Artists"",
|
artists = EXCLUDED.artists,
|
||||||
""AlbumArtists"" = EXCLUDED.""AlbumArtists"",
|
album_artists = EXCLUDED.album_artists,
|
||||||
""LUFS"" = EXCLUDED.""LUFS"",
|
lufs = EXCLUDED.lufs,
|
||||||
""NormalizationGain"" = EXCLUDED.""NormalizationGain""",
|
normalization_gain = EXCLUDED.normalization_gain",
|
||||||
cancellationToken).ConfigureAwait(false);
|
cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user