142 lines
4.8 KiB
C#
142 lines
4.8 KiB
C#
using Microsoft.Data.SqlClient;
|
|
|
|
namespace CRAWLER.Services;
|
|
|
|
internal sealed class DatabaseInitializer
|
|
{
|
|
private readonly IDatabaseConnectionFactory _connectionFactory;
|
|
|
|
public DatabaseInitializer(IDatabaseConnectionFactory connectionFactory)
|
|
{
|
|
_connectionFactory = connectionFactory;
|
|
}
|
|
|
|
public async Task EnsureCreatedAsync(CancellationToken cancellationToken)
|
|
{
|
|
await EnsureDatabaseExistsAsync(cancellationToken);
|
|
await EnsureSchemaAsync(cancellationToken);
|
|
}
|
|
|
|
private async Task EnsureDatabaseExistsAsync(CancellationToken cancellationToken)
|
|
{
|
|
await using var connection = _connectionFactory.CreateMasterConnection();
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
var safeDatabaseName = _connectionFactory.Options.Database.Replace("]", "]]");
|
|
var sql = $@"
|
|
IF DB_ID(N'{safeDatabaseName}') IS NULL
|
|
BEGIN
|
|
CREATE DATABASE [{safeDatabaseName}];
|
|
END";
|
|
|
|
await using var command = new SqlCommand(sql, connection)
|
|
{
|
|
CommandTimeout = _connectionFactory.Options.CommandTimeoutSeconds
|
|
};
|
|
await command.ExecuteNonQueryAsync(cancellationToken);
|
|
}
|
|
|
|
private async Task EnsureSchemaAsync(CancellationToken cancellationToken)
|
|
{
|
|
await using var connection = _connectionFactory.CreateConnection();
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
var scripts = new[]
|
|
{
|
|
@"
|
|
IF OBJECT_ID(N'dbo.Instruments', N'U') IS NULL
|
|
BEGIN
|
|
CREATE TABLE dbo.Instruments
|
|
(
|
|
Id BIGINT IDENTITY(1,1) NOT NULL CONSTRAINT PK_Instruments PRIMARY KEY,
|
|
RegistryNumber NVARCHAR(64) NULL,
|
|
Name NVARCHAR(512) NOT NULL,
|
|
TypeDesignation NVARCHAR(512) NULL,
|
|
Manufacturer NVARCHAR(2000) NULL,
|
|
VerificationInterval NVARCHAR(512) NULL,
|
|
CertificateOrSerialNumber NVARCHAR(512) NULL,
|
|
AllowsBatchVerification NVARCHAR(256) NULL,
|
|
HasPeriodicVerification NVARCHAR(256) NULL,
|
|
TypeInfo NVARCHAR(256) NULL,
|
|
Purpose NVARCHAR(MAX) NULL,
|
|
Description NVARCHAR(MAX) NULL,
|
|
Software NVARCHAR(MAX) NULL,
|
|
MetrologicalCharacteristics NVARCHAR(MAX) NULL,
|
|
Completeness NVARCHAR(MAX) NULL,
|
|
Verification NVARCHAR(MAX) NULL,
|
|
RegulatoryDocuments NVARCHAR(MAX) NULL,
|
|
Applicant NVARCHAR(MAX) NULL,
|
|
TestCenter NVARCHAR(MAX) NULL,
|
|
DetailUrl NVARCHAR(1024) NULL,
|
|
SourceSystem NVARCHAR(64) NOT NULL CONSTRAINT DF_Instruments_SourceSystem DEFAULT N'Manual',
|
|
LastImportedAt DATETIME2 NULL,
|
|
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_Instruments_CreatedAt DEFAULT SYSUTCDATETIME(),
|
|
UpdatedAt DATETIME2 NOT NULL CONSTRAINT DF_Instruments_UpdatedAt DEFAULT SYSUTCDATETIME()
|
|
);
|
|
END",
|
|
@"
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM sys.indexes
|
|
WHERE name = N'UX_Instruments_RegistryNumber'
|
|
AND object_id = OBJECT_ID(N'dbo.Instruments')
|
|
)
|
|
BEGIN
|
|
CREATE UNIQUE INDEX UX_Instruments_RegistryNumber
|
|
ON dbo.Instruments (RegistryNumber)
|
|
WHERE RegistryNumber IS NOT NULL AND RegistryNumber <> N'';
|
|
END",
|
|
@"
|
|
IF OBJECT_ID(N'dbo.PdfAttachments', N'U') IS NULL
|
|
BEGIN
|
|
CREATE TABLE dbo.PdfAttachments
|
|
(
|
|
Id BIGINT IDENTITY(1,1) NOT NULL CONSTRAINT PK_PdfAttachments PRIMARY KEY,
|
|
InstrumentId BIGINT NOT NULL,
|
|
Kind NVARCHAR(128) NOT NULL,
|
|
Title NVARCHAR(256) NULL,
|
|
SourceUrl NVARCHAR(1024) NULL,
|
|
LocalPath NVARCHAR(1024) NULL,
|
|
IsManual BIT NOT NULL CONSTRAINT DF_PdfAttachments_IsManual DEFAULT (0),
|
|
CreatedAt DATETIME2 NOT NULL CONSTRAINT DF_PdfAttachments_CreatedAt DEFAULT SYSUTCDATETIME(),
|
|
CONSTRAINT FK_PdfAttachments_Instruments
|
|
FOREIGN KEY (InstrumentId) REFERENCES dbo.Instruments(Id)
|
|
ON DELETE CASCADE
|
|
);
|
|
END",
|
|
@"
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM sys.indexes
|
|
WHERE name = N'IX_PdfAttachments_InstrumentId'
|
|
AND object_id = OBJECT_ID(N'dbo.PdfAttachments')
|
|
)
|
|
BEGIN
|
|
CREATE INDEX IX_PdfAttachments_InstrumentId
|
|
ON dbo.PdfAttachments (InstrumentId, CreatedAt DESC);
|
|
END",
|
|
@"
|
|
IF NOT EXISTS (
|
|
SELECT 1
|
|
FROM sys.indexes
|
|
WHERE name = N'UX_PdfAttachments_InstrumentId_SourceUrl'
|
|
AND object_id = OBJECT_ID(N'dbo.PdfAttachments')
|
|
)
|
|
BEGIN
|
|
CREATE UNIQUE INDEX UX_PdfAttachments_InstrumentId_SourceUrl
|
|
ON dbo.PdfAttachments (InstrumentId, SourceUrl)
|
|
WHERE SourceUrl IS NOT NULL AND SourceUrl <> N'';
|
|
END"
|
|
};
|
|
|
|
foreach (var script in scripts)
|
|
{
|
|
await using var command = new SqlCommand(script, connection)
|
|
{
|
|
CommandTimeout = _connectionFactory.Options.CommandTimeoutSeconds
|
|
};
|
|
await command.ExecuteNonQueryAsync(cancellationToken);
|
|
}
|
|
}
|
|
}
|