MySqlPlus/MySqlPlus/MySqlSession.cs

376 lines
12 KiB
C#

using Microsoft.VisualBasic;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace MontoyaTech.MySqlPlus
{
/// <summary>
/// The outline of a MySqlSession which contains a MySqlManagedConnection
/// and a few other help functions.
/// </summary>
public class MySqlSession : IDisposable
{
/// <summary>
/// Returns whether or not this MySqlSession has a valid connection.
/// </summary>
public bool IsConnected
{
get
{
return this.Connection != null && this.Connection.IsConnected;
}
}
/// <summary>
/// The underlying MySql Connection that this Session is using.
/// </summary>
public MySqlManagedConnection Connection = null;
/// <summary>
/// Creates a new default MySqlSession.
/// </summary>
public MySqlSession() { }
/// <summary>
/// Creates a new MySqlSession with a connection string.
/// </summary>
/// <param name="connectionString"></param>
public MySqlSession(string connectionString)
{
this.Connection = new MySqlManagedConnection(connectionString);
}
/// <summary>
/// Creates a new MySqlSession with a given connection.
/// </summary>
/// <param name="connection"></param>
public MySqlSession(MySqlManagedConnection connection)
{
this.Connection = connection;
}
/// <summary>
/// Inserts a new row in the db and returns it's id.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="row"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public ulong Insert<T>(T row)
{
var command = new MySqlCommand();
//Get the type of T
var type = typeof(T);
//Get the row information.
var rowAttribute = type.GetCustomAttribute<MySqlRow>();
//Get all the fields.
var fields = type.GetFields();
if (fields == null || fields.Length == 0)
throw new Exception("Found no public fields on given row.");
//Start building the query.
var builder = new StringBuilder();
//Write the insert section.
builder.Append($"INSERT INTO `{(rowAttribute == null || string.IsNullOrWhiteSpace(rowAttribute.Name) ? type.Name : rowAttribute.Name)}` ");
//Write the set values section.
builder.Append("SET ");
FieldInfo idField = null;
bool seperate = false;
for (int i = 0; i < fields.Length; i++)
{
var column = fields[i].GetCustomAttribute<MySqlColumn>();
if (column == null)
continue;
//Skip id columns because they are auto incremented.
if (column.Id)
{
idField = fields[i];
continue;
}
if (seperate)
builder.Append(", ");
builder.Append($"`{(string.IsNullOrWhiteSpace(column.Name) ? fields[i].Name : column.Name)}` = @{i}");
command.Parameters.AddWithValue($"@{i}", fields[i].GetValue(row));
seperate = true;
}
//Execute the insert command.
command.CommandText = builder.ToString();
this.Connection.ExecuteNonQuery(command);
//Set the id on the row if we can.
if (idField != null)
{
if (Type.GetTypeCode(idField.FieldType) == TypeCode.UInt64)
idField.SetValue(row, (ulong)command.LastInsertedId);
else
idField.SetValue(row, command.LastInsertedId);
}
return (ulong)command.LastInsertedId;
}
/// <summary>
/// Updates a row in the db.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="row"></param>
public void Update<T>(T row)
{
var command = new MySqlCommand();
//Get the type of T
var type = typeof(T);
//Get the row information.
var rowAttribute = type.GetCustomAttribute<MySqlRow>();
//Get all the fields.
var fields = type.GetFields();
if (fields == null || fields.Length == 0)
throw new Exception("Found no public fields on given row.");
//Start building the query.
var builder = new StringBuilder();
//Write the update section
builder.Append($"UPDATE `{(rowAttribute == null || string.IsNullOrWhiteSpace(rowAttribute.Name) ? type.Name : rowAttribute.Name)}` ");
//Write the set values section
builder.Append("SET ");
FieldInfo idField = null;
MySqlColumn idColumn = null;
bool seperate = false;
for (int i = 0; i < fields.Length; i++)
{
var column = fields[i].GetCustomAttribute<MySqlColumn>();
if (column == null)
continue;
//Skip id columns because they are auto incremented.
if (column.Id)
{
idField = fields[i];
idColumn = column;
continue;
}
if (seperate)
builder.Append(", ");
builder.Append($"`{(string.IsNullOrWhiteSpace(column.Name) ? fields[i].Name : column.Name)}` = @{i}");
command.Parameters.AddWithValue($"@{i}", fields[i].GetValue(row));
seperate = true;
}
//Make sure we have an id column.
if (idField == null)
throw new Exception("Given row does not contain an id column");
//Write the where clause
builder.Append($" WHERE `{(string.IsNullOrWhiteSpace(idColumn.Name) ? idField.Name : idColumn.Name)}`=@id LIMIT 1");
command.Parameters.AddWithValue("@id", idField.GetValue(row));
//Execute the command.
command.CommandText = builder.ToString();
this.Connection.ExecuteNonQuery(command);
}
/// <summary>
/// Gets a row in the db by it's id.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="id"></param>
/// <returns></returns>
public T Get<T>(ulong id)
{
var instance = typeof(T).ForceCreateInstanceFromType<T>();
this.Get<T>(instance, id);
return instance;
}
/// <summary>
/// Gets a row in the db by it's id and populates an existing instance of the row.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="row"></param>
/// <param name="id"></param>
public void Get<T>(T row, ulong id)
{
var command = new MySqlCommand();
//Get the type of T
var type = typeof(T);
//Get the row information.
var rowAttribute = type.GetCustomAttribute<MySqlRow>();
//Get all the fields.
var fields = type.GetFields();
if (fields == null || fields.Length == 0)
throw new Exception("Found no public fields on given row.");
//Find the id field
FieldInfo idField = null;
MySqlColumn idColumn = null;
for (int i = 0; i < fields.Length; i++)
{
var column = fields[i].GetCustomAttribute<MySqlColumn>();
if (column != null && column.Id)
{
idField = fields[i];
idColumn = column;
break;
}
}
//Make sure we have an id field.
if (idField == null)
throw new Exception("Failed to find id column for row.");
command.CommandText = $"SELECT * FROM `{(rowAttribute == null || string.IsNullOrWhiteSpace(rowAttribute.Name) ? type.Name : rowAttribute.Name)}` WHERE `{(string.IsNullOrWhiteSpace(idColumn.Name) ? idField.Name : idColumn.Name)}`=@id LIMIT 1";
command.Parameters.AddWithValue("@id", id);
using (var reader = this.Connection.ExecuteReader(command))
{
if (reader.Read())
{
for (int i = 0; i < fields.Length; i++)
{
var column = fields[i].GetCustomAttribute<MySqlColumn>();
if (column == null)
{
continue;
}
else if (column.Id)
{
if (Type.GetTypeCode(fields[i].FieldType) == TypeCode.UInt64)
fields[i].SetValue(row, (ulong)id);
else
fields[i].SetValue(row, (long)id);
}
else
{
column.ReadValue(row, fields[i], reader);
}
}
}
}
}
/// <summary>
/// Deletes a row in the db.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="row"></param>
public void Delete<T>(T row)
{
var command = new MySqlCommand();
//Get the type of T
var type = typeof(T);
//Get the row information.
var rowAttribute = type.GetCustomAttribute<MySqlRow>();
//Get all the fields.
var fields = type.GetFields();
if (fields == null || fields.Length == 0)
throw new Exception("Found no public fields on given row.");
//Start building the query.
var builder = new StringBuilder();
//Write the delete from section
builder.Append($"DELETE FROM `{(rowAttribute == null || string.IsNullOrWhiteSpace(rowAttribute.Name) ? type.Name : rowAttribute.Name)}` ");
//Find the id column.
FieldInfo idField = null;
MySqlColumn idColumn = null;
for (int i = 0; i < fields.Length; i++)
{
var column = fields[i].GetCustomAttribute<MySqlColumn>();
if (column != null && column.Id)
{
idField = fields[i];
idColumn = column;
break;
}
}
//Make sure we found the id
if (idField == null)
throw new Exception("Failed to find id column for row.");
//Write the where clause
builder.Append($"WHERE `{(string.IsNullOrWhiteSpace(idColumn.Name) ? idField.Name : idColumn.Name)}`=@id LIMIT 1");
command.Parameters.AddWithValue("@id", idField.GetValue(row));
command.CommandText = builder.ToString();
this.Connection.ExecuteNonQuery(command);
}
/// <summary>
/// Implicitly converts a MySqlSession to a MySqlConnection.
/// </summary>
/// <param name="session"></param>
public static implicit operator MySqlConnection(MySqlSession session)
{
return session.Connection.MySqlConnection;
}
/// <summary>
/// Disposes this MySqlSession.
/// </summary>
public virtual void Dispose()
{
if (this.Connection != null)
this.Connection.Disconnect();
}
/// <summary>
/// Cleans up this MySqlSession before GC collection.
/// </summary>
~MySqlSession()
{
if (this.Connection != null)
this.Connection.Disconnect();
}
}
}