232 lines
8.2 KiB
C#
Raw Normal View History

using MedicalDatabaseContracts;
using MedicalDatabaseContracts.Models;
using Microsoft.Extensions.Logging;
using Npgsql;
using System.Diagnostics;
using System.Text;
namespace MedicalPostgresqlDatabase
{
public abstract class AbstractPostgresqlStorage<T> : IStorage<T> where T : AbstractModel
{
protected ILogger _logger;
protected readonly string TABLE_NAME;
protected readonly string PRIMARY_KEY_COLUMN_NAME;
protected readonly string PRIMARY_KEY_SEQUENCE_NAME;
protected readonly string TIME_LOG_FILENAME_SUFFIX;
protected readonly string TIME_LOG_FOLDERNAME;
protected AbstractPostgresqlStorage(
ILogger<IStorage<T>> logger,
string tableName,
string primaryKeyColumnName,
string primary_key_sequence_name)
{
_logger = logger;
TABLE_NAME = tableName;
PRIMARY_KEY_COLUMN_NAME = primaryKeyColumnName;
PRIMARY_KEY_SEQUENCE_NAME = primary_key_sequence_name;
TIME_LOG_FILENAME_SUFFIX = "sqltimelog.csv";
TIME_LOG_FOLDERNAME = "timelogs";
}
protected abstract T CreateEntityFromReader(NpgsqlDataReader reader);
2024-05-15 23:59:52 +04:00
protected abstract Dictionary<string, object> GetEntityAttributesDictionary(T item);
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);
}
}
public virtual void Delete(int id)
{
Delete(id, out _);
}
public virtual void Delete(int id, out double elapsedMilliseconds)
{
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);
_logger.LogDebug(cmd.CommandText);
Stopwatch stopwatch = new();
stopwatch.Start();
cmd.ExecuteNonQuery();
stopwatch.Stop();
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
WriteTimeToFile(stopwatch, "DELETE");
}
public virtual T? Get(int id)
{
return Get(id, out _);
}
public virtual T? Get(int id, out double elapsedMilliseconds)
{
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);
_logger.LogDebug(cmd.CommandText);
Stopwatch stopwatch = new();
stopwatch.Start();
using var reader = cmd.ExecuteReader();
stopwatch.Stop();
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
WriteTimeToFile(stopwatch, "GET");
if (reader.Read())
{
return CreateEntityFromReader(reader);
}
return null;
}
public virtual List<T> GetAll()
{
return GetAll(out _);
}
public virtual List<T> GetAll(out double elapsedMilliseconds)
{
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);
_logger.LogDebug(cmd.CommandText);
Stopwatch stopwatch = new();
stopwatch.Start();
using var reader = cmd.ExecuteReader();
stopwatch.Stop();
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
WriteTimeToFile(stopwatch, "GETALL");
while (reader.Read())
{
items.Add(CreateEntityFromReader(reader));
}
return items;
}
public virtual void Insert(T item)
{
Insert(item, out _);
}
public virtual void Insert(T item, out double elapsedMilliseconds)
{
using var connection = GetConnection();
connection.Open();
var dict = GetEntityAttributesDictionary(item);
string namesString = "";
string valuesString = "";
foreach (var key in dict.Keys)
{
namesString += (string.IsNullOrEmpty(namesString) ? "" : ", ") + $"{key}";
if (key == PRIMARY_KEY_COLUMN_NAME)
valuesString += (string.IsNullOrEmpty(valuesString) ? "" : ", ") + $"nextval('{PRIMARY_KEY_SEQUENCE_NAME}')";
else
valuesString += (string.IsNullOrEmpty(valuesString) ? "" : ", ") + $"@{key}";
}
namesString = $"({namesString})";
valuesString = $"({valuesString})";
string[] queryBuilder = {
"INSERT INTO",
TABLE_NAME,
namesString,
"VALUES",
valuesString
};
using var cmd = new NpgsqlCommand(string.Join(' ', queryBuilder), connection);
foreach (var key in dict.Keys)
{
cmd.Parameters.AddWithValue($"@{key}", dict[key] ?? DBNull.Value);
}
_logger.LogDebug(cmd.CommandText);
Stopwatch stopwatch = new();
stopwatch.Start();
cmd.ExecuteNonQuery();
stopwatch.Stop();
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
WriteTimeToFile(stopwatch, "INSERT");
}
public virtual void Update(T item)
{
Update(item, out _);
}
public virtual void Update(T item, out double elapsedMilliseconds)
{
using var connection = GetConnection();
connection.Open();
var dict = GetEntityAttributesDictionary(item);
string setString = "";
foreach (var key in dict.Keys)
{
if (key != PRIMARY_KEY_COLUMN_NAME)
setString += (string.IsNullOrEmpty(setString) ? "" : ", ") + $"{key} = @{key}";
}
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);
foreach (var key in dict.Keys)
{
cmd.Parameters.AddWithValue($"@{key}", dict[key] ?? DBNull.Value);
}
_logger.LogDebug(cmd.CommandText);
Stopwatch stopwatch = new();
stopwatch.Start();
cmd.ExecuteNonQuery();
stopwatch.Stop();
elapsedMilliseconds = stopwatch.Elapsed.TotalMilliseconds;
WriteTimeToFile(stopwatch, "UPDATE");
}
protected NpgsqlConnection GetConnection()
{
return new NpgsqlConnection("Host=127.0.0.1;Port=5555;Username=postgres;Database=medicalbase;Password=postgres");
}
}
}