2024-05-08 00:48:57 +04:00
|
|
|
|
using MedicalDatabaseContracts;
|
|
|
|
|
using MedicalDatabaseContracts.Models;
|
2024-05-08 11:09:59 +04:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
2024-05-08 00:48:57 +04:00
|
|
|
|
using Npgsql;
|
2024-05-08 03:23:15 +04:00
|
|
|
|
using System.Diagnostics;
|
2024-05-17 01:11:47 +04:00
|
|
|
|
using System.Text;
|
2024-05-08 00:48:57 +04:00
|
|
|
|
|
|
|
|
|
namespace MedicalPostgresqlDatabase
|
|
|
|
|
{
|
|
|
|
|
public abstract class AbstractPostgresqlStorage<T> : IStorage<T> where T : AbstractModel
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
protected ILogger _logger;
|
2024-05-08 03:23:15 +04:00
|
|
|
|
protected readonly string TABLE_NAME;
|
|
|
|
|
protected readonly string PRIMARY_KEY_COLUMN_NAME;
|
2024-05-08 11:09:59 +04:00
|
|
|
|
protected readonly string PRIMARY_KEY_SEQUENCE_NAME;
|
2024-05-08 03:23:15 +04:00
|
|
|
|
|
2024-05-17 01:11:47 +04:00
|
|
|
|
protected readonly string TIME_LOG_FILENAME_SUFFIX;
|
|
|
|
|
protected readonly string TIME_LOG_FOLDERNAME;
|
|
|
|
|
|
2024-05-08 11:09:59 +04:00
|
|
|
|
protected AbstractPostgresqlStorage(
|
|
|
|
|
ILogger<IStorage<T>> logger,
|
|
|
|
|
string tableName,
|
|
|
|
|
string primaryKeyColumnName,
|
|
|
|
|
string primary_key_sequence_name)
|
2024-05-08 03:23:15 +04:00
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
_logger = logger;
|
2024-05-08 03:23:15 +04:00
|
|
|
|
TABLE_NAME = tableName;
|
|
|
|
|
PRIMARY_KEY_COLUMN_NAME = primaryKeyColumnName;
|
2024-05-08 11:09:59 +04:00
|
|
|
|
PRIMARY_KEY_SEQUENCE_NAME = primary_key_sequence_name;
|
2024-05-17 01:11:47 +04:00
|
|
|
|
|
|
|
|
|
TIME_LOG_FILENAME_SUFFIX = "sqltimelog.csv";
|
|
|
|
|
TIME_LOG_FOLDERNAME = "timelogs";
|
2024-05-08 03:23:15 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected abstract T CreateEntityFromReader(NpgsqlDataReader reader);
|
|
|
|
|
|
2024-05-15 23:59:52 +04:00
|
|
|
|
protected abstract Dictionary<string, object> GetEntityAttributesDictionary(T item);
|
2024-05-08 11:09:59 +04:00
|
|
|
|
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public void DeleteAll(out double elapsedMilliseconds)
|
|
|
|
|
{
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
|
|
|
|
using var cmd = new NpgsqlCommand($"DELETE FROM {TABLE_NAME}", connection);
|
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
stopwatch.Stop();
|
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "DELETEALL");
|
|
|
|
|
}
|
|
|
|
|
public void DeleteAll()
|
|
|
|
|
{
|
|
|
|
|
DeleteAll(out _);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void WriteTimeToFile(Stopwatch stopwatch, string filenamePrefix)
|
|
|
|
|
{
|
|
|
|
|
if (!Directory.Exists(TIME_LOG_FOLDERNAME))
|
|
|
|
|
{
|
|
|
|
|
Directory.CreateDirectory(TIME_LOG_FOLDERNAME);
|
|
|
|
|
}
|
|
|
|
|
string filename = GetType().Name + "_" + filenamePrefix + "_" + TIME_LOG_FILENAME_SUFFIX;
|
|
|
|
|
string path = Path.Combine(TIME_LOG_FOLDERNAME, filename);
|
|
|
|
|
using (StreamWriter sw = new StreamWriter(path, true))
|
|
|
|
|
{
|
|
|
|
|
sw.WriteLine(stopwatch.Elapsed.TotalMilliseconds);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 02:34:54 +04:00
|
|
|
|
public virtual void Delete(int id)
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
Delete(id, out _);
|
2024-05-08 02:34:54 +04:00
|
|
|
|
}
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public virtual void Delete(int id, out double elapsedMilliseconds)
|
2024-05-08 03:23:15 +04:00
|
|
|
|
{
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
|
|
|
|
using var cmd = new NpgsqlCommand($"DELETE FROM {TABLE_NAME} WHERE {PRIMARY_KEY_COLUMN_NAME} = @id", connection);
|
|
|
|
|
cmd.Parameters.AddWithValue("@id", id);
|
2024-05-15 14:49:38 +04:00
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
2024-05-08 03:23:15 +04:00
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
stopwatch.Stop();
|
2024-05-17 01:11:47 +04:00
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "DELETE");
|
2024-05-08 03:23:15 +04:00
|
|
|
|
}
|
2024-05-08 02:34:54 +04:00
|
|
|
|
public virtual T? Get(int id)
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
return Get(id, out _);
|
2024-05-08 02:34:54 +04:00
|
|
|
|
}
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public virtual T? Get(int id, out double elapsedMilliseconds)
|
2024-05-08 03:23:15 +04:00
|
|
|
|
{
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
2024-05-15 23:59:52 +04:00
|
|
|
|
using var cmd = new NpgsqlCommand($"SELECT * FROM {TABLE_NAME} WHERE {PRIMARY_KEY_COLUMN_NAME} = @id", connection);
|
|
|
|
|
cmd.Parameters.AddWithValue($"@id", id);
|
2024-05-15 14:49:38 +04:00
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
2024-05-08 03:23:15 +04:00
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
using var reader = cmd.ExecuteReader();
|
|
|
|
|
stopwatch.Stop();
|
2024-05-17 01:11:47 +04:00
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "GET");
|
2024-05-08 03:23:15 +04:00
|
|
|
|
if (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
return CreateEntityFromReader(reader);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-05-08 02:34:54 +04:00
|
|
|
|
public virtual List<T> GetAll()
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
return GetAll(out _);
|
2024-05-08 02:34:54 +04:00
|
|
|
|
}
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public virtual List<T> GetAll(out double elapsedMilliseconds)
|
2024-05-08 03:23:15 +04:00
|
|
|
|
{
|
|
|
|
|
var items = new List<T>();
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
|
|
|
|
using var cmd = new NpgsqlCommand($"SELECT * FROM {TABLE_NAME} ORDER BY {PRIMARY_KEY_COLUMN_NAME}", connection);
|
2024-05-15 14:49:38 +04:00
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
2024-05-08 03:23:15 +04:00
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
using var reader = cmd.ExecuteReader();
|
|
|
|
|
stopwatch.Stop();
|
2024-05-17 01:11:47 +04:00
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "GETALL");
|
2024-05-08 03:23:15 +04:00
|
|
|
|
while (reader.Read())
|
|
|
|
|
{
|
|
|
|
|
items.Add(CreateEntityFromReader(reader));
|
|
|
|
|
}
|
|
|
|
|
return items;
|
|
|
|
|
}
|
2024-05-08 02:34:54 +04:00
|
|
|
|
public virtual void Insert(T item)
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
Insert(item, out _);
|
|
|
|
|
}
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public virtual void Insert(T item, out double elapsedMilliseconds)
|
2024-05-08 11:09:59 +04:00
|
|
|
|
{
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
|
|
|
|
var dict = GetEntityAttributesDictionary(item);
|
|
|
|
|
|
|
|
|
|
string namesString = "";
|
|
|
|
|
string valuesString = "";
|
|
|
|
|
foreach (var key in dict.Keys)
|
|
|
|
|
{
|
2024-05-15 14:49:38 +04:00
|
|
|
|
namesString += (string.IsNullOrEmpty(namesString) ? "" : ", ") + $"{key}";
|
2024-05-08 11:09:59 +04:00
|
|
|
|
if (key == PRIMARY_KEY_COLUMN_NAME)
|
2024-05-15 14:49:38 +04:00
|
|
|
|
valuesString += (string.IsNullOrEmpty(valuesString) ? "" : ", ") + $"nextval('{PRIMARY_KEY_SEQUENCE_NAME}')";
|
2024-05-08 11:09:59 +04:00
|
|
|
|
else
|
2024-05-15 14:49:38 +04:00
|
|
|
|
valuesString += (string.IsNullOrEmpty(valuesString) ? "" : ", ") + $"@{key}";
|
2024-05-08 11:09:59 +04:00
|
|
|
|
}
|
|
|
|
|
namesString = $"({namesString})";
|
2024-05-15 14:49:38 +04:00
|
|
|
|
valuesString = $"({valuesString})";
|
2024-05-08 11:09:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
string[] queryBuilder = {
|
|
|
|
|
"INSERT INTO",
|
|
|
|
|
TABLE_NAME,
|
|
|
|
|
namesString,
|
|
|
|
|
"VALUES",
|
|
|
|
|
valuesString
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var cmd = new NpgsqlCommand(string.Join(' ', queryBuilder), connection);
|
|
|
|
|
|
|
|
|
|
foreach (var key in dict.Keys)
|
|
|
|
|
{
|
2024-05-16 22:45:48 +04:00
|
|
|
|
cmd.Parameters.AddWithValue($"@{key}", dict[key] ?? DBNull.Value);
|
2024-05-08 11:09:59 +04:00
|
|
|
|
}
|
2024-05-15 14:49:38 +04:00
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
2024-05-08 11:09:59 +04:00
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
stopwatch.Stop();
|
2024-05-17 01:11:47 +04:00
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "INSERT");
|
2024-05-08 02:34:54 +04:00
|
|
|
|
}
|
|
|
|
|
public virtual void Update(T item)
|
|
|
|
|
{
|
2024-05-08 11:09:59 +04:00
|
|
|
|
Update(item, out _);
|
|
|
|
|
}
|
2024-05-17 01:11:47 +04:00
|
|
|
|
public virtual void Update(T item, out double elapsedMilliseconds)
|
2024-05-08 11:09:59 +04:00
|
|
|
|
{
|
|
|
|
|
using var connection = GetConnection();
|
|
|
|
|
connection.Open();
|
|
|
|
|
|
|
|
|
|
var dict = GetEntityAttributesDictionary(item);
|
|
|
|
|
|
|
|
|
|
string setString = "";
|
|
|
|
|
foreach (var key in dict.Keys)
|
|
|
|
|
{
|
|
|
|
|
if (key != PRIMARY_KEY_COLUMN_NAME)
|
2024-05-15 14:49:38 +04:00
|
|
|
|
setString += (string.IsNullOrEmpty(setString) ? "" : ", ") + $"{key} = @{key}";
|
2024-05-08 11:09:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string[] queryBuilder = {
|
|
|
|
|
"UPDATE",
|
|
|
|
|
TABLE_NAME,
|
|
|
|
|
"SET",
|
|
|
|
|
setString,
|
|
|
|
|
"WHERE",
|
|
|
|
|
$"{PRIMARY_KEY_COLUMN_NAME} = @{PRIMARY_KEY_COLUMN_NAME}"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using var cmd = new NpgsqlCommand(string.Join(' ', queryBuilder), connection);
|
|
|
|
|
|
2024-05-15 14:49:38 +04:00
|
|
|
|
|
2024-05-08 11:09:59 +04:00
|
|
|
|
foreach (var key in dict.Keys)
|
|
|
|
|
{
|
2024-05-16 22:45:48 +04:00
|
|
|
|
cmd.Parameters.AddWithValue($"@{key}", dict[key] ?? DBNull.Value);
|
2024-05-08 11:09:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 14:49:38 +04:00
|
|
|
|
_logger.LogDebug(cmd.CommandText);
|
|
|
|
|
|
2024-05-08 11:09:59 +04:00
|
|
|
|
Stopwatch stopwatch = new();
|
|
|
|
|
stopwatch.Start();
|
|
|
|
|
cmd.ExecuteNonQuery();
|
|
|
|
|
stopwatch.Stop();
|
2024-05-17 01:11:47 +04:00
|
|
|
|
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
|
|
|
|
|
WriteTimeToFile(stopwatch, "UPDATE");
|
2024-05-08 02:34:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-08 00:48:57 +04:00
|
|
|
|
protected NpgsqlConnection GetConnection()
|
|
|
|
|
{
|
2024-05-08 01:46:11 +04:00
|
|
|
|
return new NpgsqlConnection("Host=127.0.0.1;Port=5555;Username=postgres;Database=medicalbase;Password=postgres");
|
2024-05-08 00:48:57 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|