Adding new SQL Database serializer

This commit is contained in:
FlorianDahn 2022-06-30 16:22:53 +02:00
parent 78b3fbebc8
commit 4054fa3e85
5 changed files with 333 additions and 0 deletions

View File

@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Builder;
using TelegramBotBase.Builder.Interfaces;
namespace TelegramBotBase.Extensions.Serializer.Database.MSSQL
{
public static class BotBaseBuilderExtensions
{
/// <summary>
/// Uses an Microsoft SQL Server Database to save and restore sessions.
/// </summary>
/// <param name="builder"></param>
/// <param name="ConnectionString"></param>
/// <param name="tablePrefix"></param>
/// <param name="fallbackForm"></param>
/// <returns></returns>
public static ILanguageSelectionStage UseSQLDatabase(this ISessionSerializationStage builder, String ConnectionString, Type fallbackForm = null, String tablePrefix = "tgb_")
{
var serializer = new MSSQLSerializer(ConnectionString, tablePrefix, fallbackForm);
builder.UseSerialization(serializer);
return builder as BotBaseBuilder;
}
/// <summary>
/// Uses an Microsoft SQL Server Database to save and restore sessions.
/// </summary>
/// <param name="builder"></param>
/// <param name="HostOrIP"></param>
/// <param name="UserId"></param>
/// <param name="Password"></param>
/// <param name="DatabaseName"></param>
/// <param name="tablePrefix"></param>
/// <param name="fallbackForm"></param>
/// <returns></returns>
public static ILanguageSelectionStage UseSQLDatabase(this ISessionSerializationStage builder, String HostOrIP, String DatabaseName, String UserId, String Password, Type fallbackForm = null, String tablePrefix = "tgb_")
{
var connectionString = $"Server={HostOrIP}; Database={DatabaseName}; User Id={UserId}; Password={Password}; TrustServerCertificate=true;";
var serializer = new MSSQLSerializer(connectionString, tablePrefix, fallbackForm);
builder.UseSerialization(serializer);
return builder as BotBaseBuilder;
}
/// <summary>
/// Uses an Microsoft SQL Server Database with Windows Authentication to save and restore sessions.
/// </summary>
/// <param name="builder"></param>
/// <param name="HostOrIP"></param>
/// <param name="DatabaseName"></param>
/// <param name="tablePrefix"></param>
/// <param name="fallbackForm"></param>
/// <returns></returns>
public static ILanguageSelectionStage UseSQLDatabase(this ISessionSerializationStage builder, String HostOrIP, String DatabaseName, bool IntegratedSecurity = true, Type fallbackForm = null, String tablePrefix = "tgb_")
{
if (!IntegratedSecurity)
throw new ArgumentOutOfRangeException();
var connectionString = $"Server={HostOrIP}; Database={DatabaseName}; Integrated Security=true; TrustServerCertificate=true;";
var serializer = new MSSQLSerializer(connectionString, tablePrefix, fallbackForm);
builder.UseSerialization(serializer);
return builder as BotBaseBuilder;
}
}
}

View File

@ -0,0 +1,186 @@
using TelegramBotBase.Interfaces;
using TelegramBotBase.Builder.Interfaces;
using System;
using TelegramBotBase.Base;
using TelegramBotBase.Args;
using TelegramBotBase.Form;
using Microsoft.Data.SqlClient;
using System.Data;
namespace TelegramBotBase.Extensions.Serializer.Database.MSSQL
{
public class MSSQLSerializer : IStateMachine
{
public Type FallbackStateForm { get; set; }
public string ConnectionString { get; }
public String TablePrefix { get; set; }
/// <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)
{
if (ConnectionString is null)
{
throw new ArgumentNullException(nameof(ConnectionString));
}
this.ConnectionString = ConnectionString;
this.TablePrefix = tablePrefix;
this.FallbackStateForm = fallbackStateForm;
if (this.FallbackStateForm != null && !this.FallbackStateForm.IsSubclassOf(typeof(FormBase)))
{
throw new ArgumentException("FallbackStateForm is not a subclass of FormBase");
}
}
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 data_command = connection.CreateCommand();
data_command.CommandText = "SELECT [key], value, type FROM " + TablePrefix + "devices_sessions_data WHERE deviceId = @deviceId";
data_command.Parameters.Add(new SqlParameter("@deviceId", r["deviceId"]));
var data_table = new DataTable();
using (var dataAdapter2 = new SqlDataAdapter(data_command))
{
dataAdapter2.Fill(data_table);
foreach (DataRow r2 in data_table.Rows)
{
var key = r2["key"].ToString();
var type = Type.GetType(r2["type"].ToString());
var value = Newtonsoft.Json.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 clear_command = connection.CreateCommand();
clear_command.CommandText = $"DELETE FROM {TablePrefix}devices_sessions_data";
clear_command.ExecuteNonQuery();
clear_command.CommandText = $"DELETE FROM {TablePrefix}devices_sessions";
clear_command.ExecuteNonQuery();
//Prepare new session commands
var session_command = connection.CreateCommand();
var data_command = connection.CreateCommand();
session_command.CommandText = "INSERT INTO " + TablePrefix + "devices_sessions (deviceId, deviceTitle, FormUri, QualifiedName) VALUES (@deviceId, @deviceTitle, @FormUri, @QualifiedName)";
session_command.Parameters.Add(new SqlParameter("@deviceId", ""));
session_command.Parameters.Add(new SqlParameter("@deviceTitle", ""));
session_command.Parameters.Add(new SqlParameter("@FormUri", ""));
session_command.Parameters.Add(new SqlParameter("@QualifiedName", ""));
data_command.CommandText = "INSERT INTO " + TablePrefix + "devices_sessions_data (deviceId, [key], value, type) VALUES (@deviceId, @key, @value, @type)";
data_command.Parameters.Add(new SqlParameter("@deviceId", ""));
data_command.Parameters.Add(new SqlParameter("@key", ""));
data_command.Parameters.Add(new SqlParameter("@value", ""));
data_command.Parameters.Add(new SqlParameter("@type", ""));
//Store session data in database
foreach (var state in container.States)
{
session_command.Parameters["@deviceId"].Value = state.DeviceId;
session_command.Parameters["@deviceTitle"].Value = state.ChatTitle ?? "";
session_command.Parameters["@FormUri"].Value = state.FormUri;
session_command.Parameters["@QualifiedName"].Value = state.QualifiedName;
session_command.ExecuteNonQuery();
foreach (var data in state.Values)
{
data_command.Parameters["@deviceId"].Value = state.DeviceId;
data_command.Parameters["@key"].Value = data.Key;
var type = data.Value.GetType();
if (type.IsPrimitive || type.Equals(typeof(string)))
{
data_command.Parameters["@value"].Value = data.Value;
}
else
{
data_command.Parameters["@value"].Value = Newtonsoft.Json.JsonConvert.SerializeObject(data.Value);
}
data_command.Parameters["@type"].Value = type.AssemblyQualifiedName;
data_command.ExecuteNonQuery();
}
}
connection.Close();
}
}
}
}

View File

@ -0,0 +1,8 @@
# TelegramBotBase.Extensions.Images
[![NuGet version (TelegramBotBase)](https://img.shields.io/nuget/v/TelegramBotBase.Extensions.Serializer.Database.MSSQL.svg?style=flat-square)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Serializer.Database.MSSQL/)
[![telegram chat](https://img.shields.io/badge/Support_Chat-Telegram-blue.svg?style=flat-square)](https://www.t.me/tgbotbase)
[![license](https://img.shields.io/github/license/MajMcCloud/telegrambotframework.svg?style=flat-square&maxAge=2592000&label=License)](https://raw.githubusercontent.com/MajMcCloud/TelegramBotFramework/master/LICENCE.md)
[![downloads](https://img.shields.io/nuget/dt/TelegramBotBase.Extensions.Serializer.Database.MSSQL.svg?style=flat-square&label=Package%20Downloads)](https://www.nuget.org/packages/TelegramBotBase.Extensions.Serializer.Database.MSSQL)

View File

@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net5;netcoreapp3.1;net6</TargetFrameworks>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<RepositoryUrl>https://github.com/MajMcCloud/TelegramBotFramework</RepositoryUrl>
<PackageProjectUrl>https://github.com/MajMcCloud/TelegramBotFramework</PackageProjectUrl>
<Copyright>MIT</Copyright>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="4.1.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\TelegramBotBase\TelegramBotBase.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,37 @@
USE [telegram_bot]
GO
/****** Object: Table [dbo].[tgb_devices_sessions] Script Date: 30.06.2022 16:22:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tgb_devices_sessions](
[deviceId] [bigint] NOT NULL,
[deviceTitle] [nvarchar](512) NOT NULL,
[FormUri] [nvarchar](512) NOT NULL,
[QualifiedName] [nvarchar](512) NOT NULL,
CONSTRAINT [PK_tgb_devices_sessions_1] PRIMARY KEY CLUSTERED
(
[deviceId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[tgb_devices_sessions_data] Script Date: 30.06.2022 16:22:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[tgb_devices_sessions_data](
[Id] [uniqueidentifier] NOT NULL,
[deviceId] [bigint] NOT NULL,
[key] [nvarchar](512) NOT NULL,
[value] [nvarchar](max) NOT NULL,
[type] [nvarchar](512) NOT NULL,
CONSTRAINT [PK_tgb_devices_session_data] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[tgb_devices_sessions_data] ADD CONSTRAINT [DF_tgb_devices_session_data_Id] DEFAULT (newid()) FOR [Id]
GO