Fixed DbContext usage on Provider

This commit is contained in:
JPVenson
2025-01-27 16:35:46 +00:00
parent aa811eb1e3
commit 9d1c4ea169
10 changed files with 35 additions and 18 deletions

View File

@@ -10,6 +10,11 @@ namespace Jellyfin.Server.Implementations;
/// </summary>
public interface IJellyfinDatabaseProvider : IAsyncDisposable
{
/// <summary>
/// Gets or Sets the Database Factory when initialisaition is done.
/// </summary>
IDbContextFactory<JellyfinDbContext>? DbContextFactory { get; set; }
/// <summary>
/// Initialises jellyfins EFCore database access.
/// </summary>

View File

@@ -45,7 +45,7 @@
<ProjectReference Include="..\..\Jellyfin.Data\Jellyfin.Data.csproj" />
<ProjectReference Include="..\..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
<ProjectReference Include="..\..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
<!-- <ProjectReference Include="..\..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" /> -->
</ItemGroup>
</Project>

View File

@@ -19,7 +19,7 @@ namespace Jellyfin.Server.Implementations.Migrations
return new JellyfinDbContext(
optionsBuilder.Options,
NullLogger<JellyfinDbContext>.Instance,
new SqliteDatabaseProvider(null!, null!, NullLogger<SqliteDatabaseProvider>.Instance));
new SqliteDatabaseProvider(null!, NullLogger<SqliteDatabaseProvider>.Instance));
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using Jellyfin.Server.Implementations.ValueConverters;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Jellyfin.Server.Implementations
{
/// <summary>
/// Model builder extensions.
/// </summary>
public static class ModelBuilderExtensions
{
/// <summary>
/// Specify value converter for the object type.
/// </summary>
/// <param name="modelBuilder">The model builder.</param>
/// <param name="converter">The <see cref="ValueConverter{TModel,TProvider}"/>.</param>
/// <typeparam name="T">The type to convert.</typeparam>
/// <returns>The modified <see cref="ModelBuilder"/>.</returns>
public static ModelBuilder UseValueConverterForType<T>(this ModelBuilder modelBuilder, ValueConverter converter)
{
var type = typeof(T);
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
if (property.ClrType == type)
{
property.SetValueConverter(converter);
}
}
}
return modelBuilder;
}
/// <summary>
/// Specify the default <see cref="DateTimeKind"/>.
/// </summary>
/// <param name="modelBuilder">The model builder to extend.</param>
/// <param name="kind">The <see cref="DateTimeKind"/> to specify.</param>
public static void SetDefaultDateTimeKind(this ModelBuilder modelBuilder, DateTimeKind kind)
{
modelBuilder.UseValueConverterForType<DateTime>(new DateTimeKindValueConverter(kind));
modelBuilder.UseValueConverterForType<DateTime?>(new DateTimeKindValueConverter(kind));
}
}
}

View File

@@ -10,6 +10,7 @@ namespace Jellyfin.Database.Providers.SqLite;
/// <summary>
/// Configures jellyfin to use an SqLite database.
/// </summary>
[JellyfinDatabaseProviderKey("Jellyfin-SqLite")]
public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
{
private readonly IApplicationPaths _applicationPaths;
@@ -18,17 +19,16 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
/// <summary>
/// Initializes a new instance of the <see cref="SqliteDatabaseProvider"/> class.
/// </summary>
/// <param name="dbContextFactory">The Db context to interact with the database.</param>
/// <param name="applicationPaths">Service to construct the fallback when the old data path configuration is used.</param>
/// <param name="logger">A logger.</param>
public SqliteDatabaseProvider(IDbContextFactory<JellyfinDbContext> dbContextFactory, IApplicationPaths applicationPaths, ILogger<SqliteDatabaseProvider> logger)
public SqliteDatabaseProvider(IApplicationPaths applicationPaths, ILogger<SqliteDatabaseProvider> logger)
{
DbContextFactory = dbContextFactory;
_applicationPaths = applicationPaths;
_logger = logger;
}
private IDbContextFactory<JellyfinDbContext> DbContextFactory { get; }
/// <inheritdoc/>
public IDbContextFactory<JellyfinDbContext>? DbContextFactory { get; set; }
/// <inheritdoc/>
public void Initialise(DbContextOptionsBuilder options)
@@ -41,7 +41,7 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
/// <inheritdoc/>
public async Task RunScheduledOptimisation(CancellationToken cancellationToken)
{
var context = await DbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
await using (context.ConfigureAwait(false))
{
if (context.Database.IsSqlite())
@@ -67,7 +67,7 @@ public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider
public async ValueTask DisposeAsync()
{
// Run before disposing the application
var context = await DbContextFactory.CreateDbContextAsync().ConfigureAwait(false);
var context = await DbContextFactory!.CreateDbContextAsync().ConfigureAwait(false);
await using (context.ConfigureAwait(false))
{
await context.Database.ExecuteSqlRawAsync("PRAGMA optimize").ConfigureAwait(false);

View File

@@ -0,0 +1,21 @@
using System;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Jellyfin.Server.Implementations.ValueConverters
{
/// <summary>
/// ValueConverter to specify kind.
/// </summary>
public class DateTimeKindValueConverter : ValueConverter<DateTime, DateTime>
{
/// <summary>
/// Initializes a new instance of the <see cref="DateTimeKindValueConverter"/> class.
/// </summary>
/// <param name="kind">The kind to specify.</param>
/// <param name="mappingHints">The mapping hints.</param>
public DateTimeKindValueConverter(DateTimeKind kind, ConverterMappingHints? mappingHints = null)
: base(v => v.ToUniversalTime(), v => DateTime.SpecifyKind(v, kind), mappingHints)
{
}
}
}