Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="10.7.0" />
<PackageVersion Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.19.1" />
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.19.1" />
<!-- EF Core patch version must not exceed RuntimeFrameworkVersion (Custom.Build.props), which pins the Microsoft.Extensions.* packages -->
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
<PackageVersion Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.5" />
<PackageVersion Include="Mindscape.Raygun4Net.NetCore" Version="11.2.5" />
Expand Down Expand Up @@ -92,6 +98,8 @@
<PackageVersion Include="System.IO.Hashing" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="System.Threading.RateLimiting" Version="$(RuntimeFrameworkVersion)" />
<PackageVersion Include="Microsoft.Data.SqlClient" Version="6.1.5" />
<PackageVersion Include="Azure.Core" Version="1.53.0" />
</ItemGroup>
<ItemGroup>
<GlobalPackageReference Include="Microsoft.Build.Artifacts" Version="6.1.63" />
Expand Down
2 changes: 2 additions & 0 deletions src/ProjectReferences.Persisters.Primary.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<Project>

<ItemGroup Label="Persisters">
<ProjectReference Include="..\ServiceControl.Persistence.EFCore.PostgreSql\ServiceControl.Persistence.EFCore.PostgreSql.csproj" ReferenceOutputAssembly="false" Private="false" />
<ProjectReference Include="..\ServiceControl.Persistence.EFCore.SqlServer\ServiceControl.Persistence.EFCore.SqlServer.csproj" ReferenceOutputAssembly="false" Private="false" />
<ProjectReference Include="..\ServiceControl.Persistence.RavenDB\ServiceControl.Persistence.RavenDB.csproj" ReferenceOutputAssembly="false" Private="false" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[*.cs]

# Justification: ServiceControl app has no synchronization context
dotnet_diagnostic.CA2007.severity = none

# Disable style rules for auto-generated EF migrations
[Migrations/**.cs]
dotnet_diagnostic.IDE0065.severity = none
generated_code = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace ServiceControl.Persistence.EFCore.PostgreSql;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ServiceControl.Persistence.EFCore.Abstractions;

class PostgreSqlPersistence(PostgreSqlPersisterSettings settings) : BasePersistence, IPersistence
{
public void AddPersistence(IServiceCollection services)
{
RegisterSettings(services);
ConfigureDbContext(services);
RegisterDataStores(services);
}

public void AddInstaller(IServiceCollection services)
{
RegisterSettings(services);
ConfigureDbContext(services);
}

void RegisterSettings(IServiceCollection services)
{
services.AddSingleton<PersistenceSettings>(settings);
services.AddSingleton<EFPersisterSettings>(settings);
services.AddSingleton(settings);
}

void ConfigureDbContext(IServiceCollection services) =>
services.AddPooledDbContextFactory<PostgreSqlServiceControlDbContext>(options =>
options.UseNpgsql(settings.ConnectionString, npgsql => npgsql.CommandTimeout(settings.CommandTimeout)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ServiceControl.Persistence.EFCore.PostgreSql;

using Microsoft.Extensions.Logging;
using ServiceControl.Infrastructure;
using ServiceControl.Persistence.EFCore.Abstractions;

class PostgreSqlPersistenceConfiguration : EFPersistenceConfigurationBase
{
public override IPersistence Create(PersistenceSettings settings)
{
// Temporary until the persister is fully implemented
LoggerUtil.CreateStaticLogger<PostgreSqlPersistenceConfiguration>()
.LogError("The PostgreSQL persistence is still under development and is not ready for use");

return new PostgreSqlPersistence((PostgreSqlPersisterSettings)settings);
}

protected override EFPersisterSettings CreateSettings(string connectionString) =>
new PostgreSqlPersisterSettings { ConnectionString = connectionString };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ServiceControl.Persistence.EFCore.PostgreSql;

using ServiceControl.Persistence.EFCore.Abstractions;

public class PostgreSqlPersisterSettings : EFPersisterSettings
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ServiceControl.Persistence.EFCore.PostgreSql;

using Microsoft.EntityFrameworkCore;
using ServiceControl.Persistence.EFCore.DbContexts;

public class PostgreSqlServiceControlDbContext(DbContextOptions<PostgreSqlServiceControlDbContext> options) : ServiceControlDbContext(options)
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace ServiceControl.Persistence.EFCore.PostgreSql;

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

/// <summary>
/// Design-time factory used by the dotnet-ef tooling (e.g. dotnet ef migrations add).
/// </summary>
public class PostgreSqlServiceControlDbContextFactory : IDesignTimeDbContextFactory<PostgreSqlServiceControlDbContext>
{
public PostgreSqlServiceControlDbContext CreateDbContext(string[] args)
{
var connectionString = Environment.GetEnvironmentVariable("SERVICECONTROL_DATABASE_CONNECTIONSTRING")
?? "Host=localhost;Port=5432;Database=servicecontrol;Username=postgres;Password=postgres";

var optionsBuilder = new DbContextOptionsBuilder<PostgreSqlServiceControlDbContext>();
optionsBuilder.UseNpgsql(connectionString);

return new PostgreSqlServiceControlDbContext(optionsBuilder.Options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
</PropertyGroup>

<ItemGroup>
<!-- Private=false & ExcludeAssets=runtime prevent repeatedly including binary dependencies of ServiceControl.Persistence and its dependencies in each persister directory -->
<ProjectReference Include="../ServiceControl.Configuration/ServiceControl.Configuration.csproj" Private="false" ExcludeAssets="runtime" />
<ProjectReference Include="../ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj" Private="false" ExcludeAssets="runtime" />
<ProjectReference Include="../ServiceControl.Persistence/ServiceControl.Persistence.csproj" Private="false" ExcludeAssets="runtime" />
</ItemGroup>

<ItemGroup>
<!-- Not Private=false or ExcludeAssets because the shared EF Core assembly ships inside this persister's folder -->
<ProjectReference Include="../ServiceControl.Persistence.EFCore/ServiceControl.Persistence.EFCore.csproj" />
</ItemGroup>

<ItemGroup>
<!-- Design-time only, for dotnet-ef tooling. Debug-only so it (and its Roslyn dependency tail) stays out of the shipped Release artifact -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
</ItemGroup>

<ItemGroup>
<None Update="persistence.manifest" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl/Persisters/PostgreSQL" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"Name": "PostgreSQL",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should Sql vs SQL casing be standardised on Sql?
Note that we already use PostgreSql elsewhere.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

"DisplayName": "PostgreSQL",
"Description": "PostgreSQL ServiceControl persister",
"AssemblyName": "ServiceControl.Persistence.EFCore.PostgreSql",
"TypeName": "ServiceControl.Persistence.EFCore.PostgreSql.PostgreSqlPersistenceConfiguration, ServiceControl.Persistence.EFCore.PostgreSql",
"Settings": [
{
"Name": "ServiceControl/Database/ConnectionString",
"Mandatory": true
},
{
"Name": "ServiceControl/Database/CommandTimeout",
"Mandatory": false
},
{
"Name": "ServiceControl/MessageBody/StoragePath",
"Mandatory": false
},
{
"Name": "ServiceControl/MessageBody/MinCompressionSize",
"Mandatory": false
}
]
}
9 changes: 9 additions & 0 deletions src/ServiceControl.Persistence.EFCore.SqlServer/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[*.cs]

# Justification: ServiceControl app has no synchronization context
dotnet_diagnostic.CA2007.severity = none

# Disable style rules for auto-generated EF migrations
[Migrations/**.cs]
dotnet_diagnostic.IDE0065.severity = none
generated_code = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
</PropertyGroup>

<ItemGroup>
<!-- Private=false & ExcludeAssets=runtime prevent repeatedly including binary dependencies of ServiceControl.Persistence and its dependencies in each persister directory -->
<ProjectReference Include="../ServiceControl.Configuration/ServiceControl.Configuration.csproj" Private="false" ExcludeAssets="runtime" />
<ProjectReference Include="../ServiceControl.Infrastructure/ServiceControl.Infrastructure.csproj" Private="false" ExcludeAssets="runtime" />
<ProjectReference Include="../ServiceControl.Persistence/ServiceControl.Persistence.csproj" Private="false" ExcludeAssets="runtime" />
</ItemGroup>

<ItemGroup>
<!-- Not Private=false or ExcludeAssets because the shared EF Core assembly ships inside this persister's folder -->
<ProjectReference Include="../ServiceControl.Persistence.EFCore/ServiceControl.Persistence.EFCore.csproj" />
</ItemGroup>

<ItemGroup>
<!-- Design-time only, for dotnet-ef tooling. Debug-only so it (and its Roslyn dependency tail) stays out of the shipped Release artifact -->
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" Condition="'$(Configuration)' == 'Debug'" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
</ItemGroup>

<ItemGroup>
<None Update="persistence.manifest" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

<ItemGroup>
<Artifact Include="$(OutputPath)" DestinationFolder="$(ArtifactsPath)Particular.ServiceControl/Persisters/SQLServer" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace ServiceControl.Persistence.EFCore.SqlServer;

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using ServiceControl.Persistence.EFCore.Abstractions;

class SqlServerPersistence(SqlServerPersisterSettings settings) : BasePersistence, IPersistence
{
public void AddPersistence(IServiceCollection services)
{
RegisterSettings(services);
ConfigureDbContext(services);
RegisterDataStores(services);
}

public void AddInstaller(IServiceCollection services)
{
RegisterSettings(services);
ConfigureDbContext(services);
}

void RegisterSettings(IServiceCollection services)
{
services.AddSingleton<PersistenceSettings>(settings);
services.AddSingleton<EFPersisterSettings>(settings);
services.AddSingleton(settings);
}

void ConfigureDbContext(IServiceCollection services) =>
services.AddPooledDbContextFactory<SqlServerServiceControlDbContext>(options =>
options.UseSqlServer(settings.ConnectionString, sqlServer => sqlServer.CommandTimeout(settings.CommandTimeout)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace ServiceControl.Persistence.EFCore.SqlServer;

using Microsoft.Extensions.Logging;
using ServiceControl.Infrastructure;
using ServiceControl.Persistence.EFCore.Abstractions;

class SqlServerPersistenceConfiguration : EFPersistenceConfigurationBase
{
public override IPersistence Create(PersistenceSettings settings)
{
// Temporary until the persister is fully implemented
LoggerUtil.CreateStaticLogger<SqlServerPersistenceConfiguration>()
.LogError("The SQL Server persistence is still under development and is not ready for use");

return new SqlServerPersistence((SqlServerPersisterSettings)settings);
}

protected override EFPersisterSettings CreateSettings(string connectionString) =>
new SqlServerPersisterSettings { ConnectionString = connectionString };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ServiceControl.Persistence.EFCore.SqlServer;

using ServiceControl.Persistence.EFCore.Abstractions;

public class SqlServerPersisterSettings : EFPersisterSettings
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace ServiceControl.Persistence.EFCore.SqlServer;

using Microsoft.EntityFrameworkCore;
using ServiceControl.Persistence.EFCore.DbContexts;

public class SqlServerServiceControlDbContext(DbContextOptions<SqlServerServiceControlDbContext> options) : ServiceControlDbContext(options)
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace ServiceControl.Persistence.EFCore.SqlServer;

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

/// <summary>
/// Design-time factory used by the dotnet-ef tooling (e.g. dotnet ef migrations add).
/// </summary>
public class SqlServerServiceControlDbContextFactory : IDesignTimeDbContextFactory<SqlServerServiceControlDbContext>
{
public SqlServerServiceControlDbContext CreateDbContext(string[] args)
{
var connectionString = Environment.GetEnvironmentVariable("SERVICECONTROL_DATABASE_CONNECTIONSTRING")
?? "Server=localhost;Database=ServiceControl;Trusted_Connection=True;TrustServerCertificate=True";

var optionsBuilder = new DbContextOptionsBuilder<SqlServerServiceControlDbContext>();
optionsBuilder.UseSqlServer(connectionString);

return new SqlServerServiceControlDbContext(optionsBuilder.Options);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"Name": "SQLServer",
"DisplayName": "SQL Server",
"Description": "SQL Server ServiceControl persister",
"AssemblyName": "ServiceControl.Persistence.EFCore.SqlServer",
"TypeName": "ServiceControl.Persistence.EFCore.SqlServer.SqlServerPersistenceConfiguration, ServiceControl.Persistence.EFCore.SqlServer",
"Settings": [
{
"Name": "ServiceControl/Database/ConnectionString",
"Mandatory": true
},
{
"Name": "ServiceControl/Database/CommandTimeout",
"Mandatory": false
},
{
"Name": "ServiceControl/MessageBody/StoragePath",
"Mandatory": false
},
{
"Name": "ServiceControl/MessageBody/MinCompressionSize",
"Mandatory": false
}
]
}
9 changes: 9 additions & 0 deletions src/ServiceControl.Persistence.EFCore/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[*.cs]

# Justification: ServiceControl app has no synchronization context
dotnet_diagnostic.CA2007.severity = none

# Disable style rules for auto-generated EF migrations
[Migrations/**.cs]
dotnet_diagnostic.IDE0065.severity = none
generated_code = true
Loading
Loading