RCM/RCM/DataSource/MySQL/MySQL.cs

147 lines
6.2 KiB
C#

using MySqlConnector;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace RCM {
[DisplayName("MySQL/MariaDB")]
[Serializable]
public class MySQL : IDataSource {
public string Title { get; set; }
public HashSet<Guid> ExpandedNodes { get; } = new HashSet<Guid>();
public string Host { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public string Database { get; set; }
public string AESPassword { get; set; }
[NonSerialized]
private MySqlConnection _connection;
[NonSerialized]
private MySQLControl _control;
public override string ToString() => Title;
private MySqlConnection CreateConnection(string host, string username, string password, string database) {
string[] hostport = host.Split(':');
string port = hostport.Length > 1 ? hostport[1] : "3306";
return new MySqlConnection(string.Format("server={0};port={1};user={2};password={3};database={4}", hostport[0], port, username, password, database));
}
private void OpenConnection() {
if (_connection == null) {
_connection = CreateConnection(Host, Username, Password, Database);
}
_connection.Open();
}
public Dictionary<Guid, IRecord> SelectAll() {
Dictionary<Guid, IRecord> records = new Dictionary<Guid, IRecord>();
OpenConnection();
using (MySqlCommand command = new MySqlCommand("SELECT `data`, LENGTH(`data`) AS `datalength` FROM `data`", _connection))
using (MySqlDataReader reader = command.ExecuteReader()) {
while (reader.Read()) {
int dataBytesLength = reader.GetInt32(1);
byte[] dataBytes = new byte[dataBytesLength];
reader.GetBytes(0, 0, dataBytes, 0, dataBytesLength);
IRecord record = (IRecord)ConfigSerializer.DecryptObject(dataBytes, AESPassword);
records.Add(record.Id, record);
}
}
_connection.Close();
return records;
}
public void Insert(IRecord record) {
OpenConnection();
using (MySqlCommand command = new MySqlCommand("INSERT INTO `data` (`id`, `group`, `data`) VALUES (@id, @group, @data)", _connection)) {
command.Parameters.AddWithValue("@id", record.Id.ToByteArray());
if (record.GroupId == Guid.Empty) {
command.Parameters.AddWithValue("@group", null);
} else {
command.Parameters.AddWithValue("@group", record.GroupId.ToByteArray());
}
command.Parameters.AddWithValue("@data", ConfigSerializer.EncryptObject(record, AESPassword));
command.ExecuteNonQuery();
}
_connection.Close();
}
public void Update(IRecord record) {
OpenConnection();
using (MySqlCommand command = new MySqlCommand("UPDATE `data` SET `group` = @group, `data` = @data WHERE `id` = @id", _connection)) {
if (record.GroupId == Guid.Empty) {
command.Parameters.AddWithValue("@group", null);
} else {
command.Parameters.AddWithValue("@group", record.GroupId.ToByteArray());
}
command.Parameters.AddWithValue("@data", ConfigSerializer.EncryptObject(record, AESPassword));
command.Parameters.AddWithValue("@id", record.Id.ToByteArray());
command.ExecuteNonQuery();
}
_connection.Close();
}
public void Delete(IRecord record) {
OpenConnection();
using (MySqlCommand command = new MySqlCommand("DELETE FROM `data` WHERE `id` = @id", _connection)) {
command.Parameters.AddWithValue("@id", record.Id.ToByteArray());
command.ExecuteNonQuery();
}
_connection.Close();
}
public UserControl GetControl() {
if (_control == null || _control.IsDisposed) {
_control = new MySQLControl(this);
}
return _control;
}
public void UpdateFromControl() {
Host = _control.textBoxHostAddress.Text;
Username = _control.textBoxUsername.Text;
Password = _control.textBoxPassword.Text;
Database = _control.textBoxDatabase.Text;
AESPassword = _control.textBoxEncPassword.Text;
_connection = null;
}
public bool SchemaExists(string host, string username, string password, string database) {
using (MySqlConnection tempConnection = CreateConnection(host, username, password, database)) {
tempConnection.Open();
using (MySqlCommand command = new MySqlCommand("SHOW TABLES LIKE \"data\"", tempConnection))
using (MySqlDataReader reader = command.ExecuteReader()) {
return reader.HasRows;
}
}
}
public void CreateSchema(string host, string username, string password, string database) {
using (MySqlConnection tempConnection = CreateConnection(host, username, password, database)) {
tempConnection.Open();
using (MySqlCommand command = new MySqlCommand(@"DROP TABLE IF EXISTS `data`;
CREATE TABLE `data` (
`id` binary(16) NOT NULL,
`group` binary(16),
`data` blob NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (`group`) REFERENCES `data`(`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;", tempConnection)) {
command.ExecuteNonQuery();
}
}
}
public string TestConnection(string host, string username, string password, string database) {
using (MySqlConnection tempConnection = CreateConnection(host, username, password, database)) {
tempConnection.Open();
using (MySqlCommand command = new MySqlCommand("SELECT VERSION()", tempConnection)) {
return (string)command.ExecuteScalar();
}
}
}
}
}