2023-09-29 18:34:33 +02:00

183 lines
7.4 KiB
C#

using System;
using System.Data;
using Microsoft.Data.SqlClient;
using Newtonsoft.Json;
using TelegramBotBase.Args;
using TelegramBotBase.Base;
using TelegramBotBase.Form;
using TelegramBotBase.Interfaces;
namespace TelegramBotBase.Extensions.Serializer.Database.MSSQL
{
public class MssqlSerializer : IStateMachine
{
/// <summary>
/// Will initialize the state machine.
/// </summary>
/// <param name="file">Path of the file and name where to save the session details.</param>
/// <param name="fallbackStateForm">
/// Type of Form which will be saved instead of Form which has
/// <seealso cref="Attributes.IgnoreState" /> attribute declared. Needs to be subclass of
/// <seealso cref="Form.FormBase" />.
/// </param>
/// <param name="overwrite">Declares of the file could be overwritten.</param>
public MssqlSerializer(string connectionString, string tablePrefix = "tgb_", Type fallbackStateForm = null)
{
ConnectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
TablePrefix = tablePrefix;
FallbackStateForm = fallbackStateForm;
if (FallbackStateForm != null && !FallbackStateForm.IsSubclassOf(typeof(FormBase)))
{
throw new ArgumentException($"{nameof(FallbackStateForm)} is not a subclass of {nameof(FormBase)}");
}
}
public string ConnectionString { get; }
public string TablePrefix { get; set; }
public Type FallbackStateForm { get; set; }
public StateContainer LoadFormStates()
{
var sc = new StateContainer();
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT deviceId, deviceTitle, FormUri, QualifiedName FROM " + TablePrefix +
"devices_sessions";
var dataTable = new DataTable();
using (var dataAdapter = new SqlDataAdapter(command))
{
dataAdapter.Fill(dataTable);
foreach (DataRow r in dataTable.Rows)
{
var se = new StateEntry
{
DeviceId = (long)r["deviceId"],
ChatTitle = r["deviceTitle"].ToString(),
FormUri = r["FormUri"].ToString(),
QualifiedName = r["QualifiedName"].ToString()
};
sc.States.Add(se);
if (se.DeviceId > 0)
{
sc.ChatIds.Add(se.DeviceId);
}
else
{
sc.GroupIds.Add(se.DeviceId);
}
var command2 = connection.CreateCommand();
command2.CommandText = "SELECT [key], value, type FROM " + TablePrefix +
"devices_sessions_data WHERE deviceId = @deviceId";
command2.Parameters.Add(new SqlParameter("@deviceId", r["deviceId"]));
var dataTable2 = new DataTable();
using (var dataAdapter2 = new SqlDataAdapter(command2))
{
dataAdapter2.Fill(dataTable2);
foreach (DataRow r2 in dataTable2.Rows)
{
var key = r2["key"].ToString();
var type = Type.GetType(r2["type"].ToString());
var value = JsonConvert.DeserializeObject(r2["value"].ToString(), type);
se.Values.Add(key, value);
}
}
}
}
connection.Close();
}
return sc;
}
public void SaveFormStates(SaveStatesEventArgs e)
{
var container = e.States;
using (var connection = new SqlConnection(ConnectionString))
{
connection.Open();
//Cleanup old Session data
var clearCommand = connection.CreateCommand();
clearCommand.CommandText = $"DELETE FROM {TablePrefix}devices_sessions_data";
clearCommand.ExecuteNonQuery();
clearCommand.CommandText = $"DELETE FROM {TablePrefix}devices_sessions";
clearCommand.ExecuteNonQuery();
//Prepare new session commands
var sessionCommand = connection.CreateCommand();
var dataCommand = connection.CreateCommand();
sessionCommand.CommandText = "INSERT INTO " + TablePrefix +
"devices_sessions (deviceId, deviceTitle, FormUri, QualifiedName) VALUES (@deviceId, @deviceTitle, @FormUri, @QualifiedName)";
sessionCommand.Parameters.Add(new SqlParameter("@deviceId", ""));
sessionCommand.Parameters.Add(new SqlParameter("@deviceTitle", ""));
sessionCommand.Parameters.Add(new SqlParameter("@FormUri", ""));
sessionCommand.Parameters.Add(new SqlParameter("@QualifiedName", ""));
dataCommand.CommandText = "INSERT INTO " + TablePrefix +
"devices_sessions_data (deviceId, [key], value, type) VALUES (@deviceId, @key, @value, @type)";
dataCommand.Parameters.Add(new SqlParameter("@deviceId", ""));
dataCommand.Parameters.Add(new SqlParameter("@key", ""));
dataCommand.Parameters.Add(new SqlParameter("@value", ""));
dataCommand.Parameters.Add(new SqlParameter("@type", ""));
//Store session data in database
foreach (var state in container.States)
{
sessionCommand.Parameters["@deviceId"].Value = state.DeviceId;
sessionCommand.Parameters["@deviceTitle"].Value = state.ChatTitle ?? "";
sessionCommand.Parameters["@FormUri"].Value = state.FormUri;
sessionCommand.Parameters["@QualifiedName"].Value = state.QualifiedName;
sessionCommand.ExecuteNonQuery();
foreach (var data in state.Values)
{
dataCommand.Parameters["@deviceId"].Value = state.DeviceId;
dataCommand.Parameters["@key"].Value = data.Key;
var type = data.Value.GetType();
if (type.IsPrimitive || type.Equals(typeof(string)))
{
dataCommand.Parameters["@value"].Value = data.Value;
}
else
{
dataCommand.Parameters["@value"].Value = JsonConvert.SerializeObject(data.Value);
}
dataCommand.Parameters["@type"].Value = type.AssemblyQualifiedName;
dataCommand.ExecuteNonQuery();
}
}
connection.Close();
}
}
}
}