using MedicalDatabaseContracts; using MedicalDatabaseContracts.Models; using Microsoft.Extensions.Logging; using Npgsql; using System.Diagnostics; namespace MedicalPostgresqlDatabase { public abstract class AbstractPostgresqlStorage : IStorage 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 AbstractPostgresqlStorage( ILogger> 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; } protected abstract T CreateEntityFromReader(NpgsqlDataReader reader); protected abstract Dictionary GetEntityAttributesDictionary(T item); public virtual void Delete(int id) { Delete(id, out _); } public virtual void Delete(int id, out long 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); Stopwatch stopwatch = new(); stopwatch.Start(); cmd.ExecuteNonQuery(); stopwatch.Stop(); elapsedMilliseconds = stopwatch.ElapsedMilliseconds; } public virtual T? Get(int id) { return Get(id, out _); } public virtual T? Get(int id, out long elapsedMilliseconds) { using var connection = GetConnection(); connection.Open(); using var cmd = new NpgsqlCommand($"SELECT * FROM {TABLE_NAME} WHERE {PRIMARY_KEY_COLUMN_NAME} = @id", connection); cmd.Parameters.AddWithValue("@id", id); Stopwatch stopwatch = new(); stopwatch.Start(); using var reader = cmd.ExecuteReader(); stopwatch.Stop(); elapsedMilliseconds = stopwatch.ElapsedMilliseconds; if (reader.Read()) { return CreateEntityFromReader(reader); } return null; } public virtual List GetAll() { return GetAll(out _); } public virtual List GetAll(out long elapsedMilliseconds) { var items = new List(); using var connection = GetConnection(); connection.Open(); using var cmd = new NpgsqlCommand($"SELECT * FROM {TABLE_NAME} ORDER BY {PRIMARY_KEY_COLUMN_NAME}", connection); Stopwatch stopwatch = new(); stopwatch.Start(); using var reader = cmd.ExecuteReader(); stopwatch.Stop(); elapsedMilliseconds = stopwatch.ElapsedMilliseconds; 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 long elapsedMilliseconds) { using var connection = GetConnection(); connection.Open(); var dict = GetEntityAttributesDictionary(item); string namesString = ""; string valuesString = ""; foreach (var key in dict.Keys) { namesString = string.Join(", ", namesString, $"{key}"); if (key == PRIMARY_KEY_COLUMN_NAME) valuesString = string.Join(", ", valuesString, $"nextval('{PRIMARY_KEY_SEQUENCE_NAME}')"); else valuesString = string.Join(", ", 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]); } Stopwatch stopwatch = new(); stopwatch.Start(); cmd.ExecuteNonQuery(); stopwatch.Stop(); elapsedMilliseconds = stopwatch.ElapsedMilliseconds; } public virtual void Update(T item) { Update(item, out _); } public virtual void Update(T item, out long 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.Join(", ", setString, $"{key} = @{key}"); } setString = $"({setString})"; string[] queryBuilder = { "UPDATE", TABLE_NAME, "SET", setString, "VALUES", 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]); } Stopwatch stopwatch = new(); stopwatch.Start(); cmd.ExecuteNonQuery(); stopwatch.Stop(); elapsedMilliseconds = stopwatch.ElapsedMilliseconds; } protected NpgsqlConnection GetConnection() { return new NpgsqlConnection("Host=127.0.0.1;Port=5555;Username=postgres;Database=medicalbase;Password=postgres"); } } }