source
Created by: Andrew
This commit is contained in:
206
trunk/Common/Data/Database.cs
Normal file
206
trunk/Common/Data/Database.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using KartExtreme.IO;
|
||||
|
||||
namespace KartExtreme.Data
|
||||
{
|
||||
public class TemporaryConnection : IDisposable
|
||||
{
|
||||
private string oldHost;
|
||||
private string oldSchema;
|
||||
private string oldUsername;
|
||||
private string oldPassword;
|
||||
|
||||
internal TemporaryConnection(string host, string schema, string username, string password)
|
||||
{
|
||||
this.oldHost = Database.Host;
|
||||
this.oldSchema = Database.Schema;
|
||||
this.oldUsername = Database.Username;
|
||||
this.oldPassword = Database.Password;
|
||||
|
||||
Database.Host = host;
|
||||
Database.Schema = schema;
|
||||
Database.Username = username;
|
||||
Database.Password = password;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Database.Host = this.oldHost;
|
||||
Database.Schema = this.oldSchema;
|
||||
Database.Username = this.oldUsername;
|
||||
Database.Password = this.oldPassword;
|
||||
}
|
||||
}
|
||||
|
||||
public class TemporarySchema : IDisposable
|
||||
{
|
||||
private string oldSchema;
|
||||
|
||||
internal TemporarySchema(string schema)
|
||||
{
|
||||
this.oldSchema = Database.Schema;
|
||||
Database.Schema = schema;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Database.Schema = this.oldSchema;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Database
|
||||
{
|
||||
public static string Host { get; set; }
|
||||
public static string Schema { get; set; }
|
||||
public static string Username { get; set; }
|
||||
public static string Password { get; set; }
|
||||
|
||||
internal static string CorrectFields(string fields)
|
||||
{
|
||||
string final = string.Empty;
|
||||
string[] tokens = fields.Replace(",", " ").Replace(";", " ").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
int processed = 0;
|
||||
|
||||
foreach (string field in tokens)
|
||||
{
|
||||
final += field;
|
||||
processed++;
|
||||
|
||||
if (processed < tokens.Length)
|
||||
{
|
||||
final += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
internal static string ConnectionString
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("server={0}; database={1}; uid={2}; password={3}; convertzerodatetime=yes;",
|
||||
Database.Host,
|
||||
Database.Schema,
|
||||
Database.Username,
|
||||
Database.Password);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Execute(string nonQuery, params object[] args)
|
||||
{
|
||||
MySqlHelper.ExecuteNonQuery(Database.ConnectionString, string.Format(nonQuery, args));
|
||||
}
|
||||
|
||||
public static string DefaultSchema
|
||||
{
|
||||
get
|
||||
{
|
||||
string name = Assembly.GetEntryAssembly().GetName().Name;
|
||||
|
||||
switch (name)
|
||||
{
|
||||
case "WvsCenter":
|
||||
return "wvsmaple-center";
|
||||
|
||||
case "WvsLogin":
|
||||
return "wvsmaple-login";
|
||||
|
||||
default:
|
||||
return "wvsmaple-game";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Test()
|
||||
{
|
||||
using (MySqlConnection connection = new MySqlConnection(Database.ConnectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
Log.Inform("Able to connect to database '{0}'.", connection.Database);
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Analyze()
|
||||
{
|
||||
using (Database.TemporarySchema("information_schema"))
|
||||
{
|
||||
Meta.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Delete(string table, string constraints, params object[] args)
|
||||
{
|
||||
Database.Execute("DELETE FROM {0} WHERE {1}", table, string.Format(constraints, args));
|
||||
}
|
||||
|
||||
public static bool Exists(string table, string constraints, params object[] args)
|
||||
{
|
||||
using (MySqlDataReader reader = MySqlHelper.ExecuteReader(Database.ConnectionString, string.Format("SELECT * FROM {0} WHERE {1}", table, string.Format(constraints, args))))
|
||||
{
|
||||
return reader.HasRows;
|
||||
}
|
||||
}
|
||||
|
||||
public static dynamic Fetch(string table, string field, string constraints, params object[] args)
|
||||
{
|
||||
object value = new Datum(table).PopulateWith(field, constraints, args).Dictionary[field];
|
||||
|
||||
if (value is DBNull)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else if (value is byte && Meta.IsBool(table, field))
|
||||
{
|
||||
return (byte)value > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteScript(string host, string username, string password, string query, params object[] args)
|
||||
{
|
||||
using (MySqlConnection connection = new MySqlConnection(string.Format("SERVER={0}; UID={1}; PASSWORD={2};", host, username, password)))
|
||||
{
|
||||
connection.Open();
|
||||
new MySqlScript(connection, string.Format(query, args)).Execute();
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExecuteFile(string host, string username, string password, string path)
|
||||
{
|
||||
using (MySqlConnection connection = new MySqlConnection(string.Format("SERVER={0}; UID={1}; PASSWORD={2};", host, username, password)))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
using (TextReader reader = new StreamReader(path))
|
||||
{
|
||||
new MySqlScript(connection, reader.ReadToEnd()).Execute();
|
||||
}
|
||||
|
||||
connection.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public static TemporaryConnection TemporaryConnection(string host, string schema, string username, string password)
|
||||
{
|
||||
return new TemporaryConnection(host, schema, username, password);
|
||||
}
|
||||
|
||||
public static TemporarySchema TemporarySchema(string schema)
|
||||
{
|
||||
return new TemporarySchema(schema);
|
||||
}
|
||||
}
|
||||
}
|
||||
307
trunk/Common/Data/Datum.cs
Normal file
307
trunk/Common/Data/Datum.cs
Normal file
@@ -0,0 +1,307 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Dynamic;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace KartExtreme.Data
|
||||
{
|
||||
public class Datums : IEnumerable<Datum>
|
||||
{
|
||||
private List<Datum> Values { get; set; }
|
||||
private string Table { get; set; }
|
||||
|
||||
public Datums(string table = null)
|
||||
{
|
||||
this.Table = table;
|
||||
}
|
||||
|
||||
internal void PopulateInternal(string fields, string constraints)
|
||||
{
|
||||
this.Values = new List<Datum>();
|
||||
|
||||
string query = string.Format("SELECT {0} FROM {1}{2}", fields == null ? "*" : Database.CorrectFields(fields), this.Table, constraints != null ? " WHERE " + constraints : string.Empty);
|
||||
|
||||
using (MySqlDataReader reader = MySqlHelper.ExecuteReader(Database.ConnectionString, query))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
dictionary.Add(reader.GetName(i), reader.GetValue(i));
|
||||
}
|
||||
|
||||
this.Values.Add(new Datum(this.Table, dictionary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void PopulateInternalFree(string query)
|
||||
{
|
||||
this.Values = new List<Datum>();
|
||||
|
||||
using (MySqlDataReader reader = MySqlHelper.ExecuteReader(Database.ConnectionString, query))
|
||||
{
|
||||
while (reader.Read())
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
dictionary.Add(reader.GetName(i), reader.GetValue(i));
|
||||
}
|
||||
|
||||
this.Values.Add(new Datum(this.Table, dictionary));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dynamic Populate()
|
||||
{
|
||||
this.PopulateInternal(null, null);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public dynamic Populate(string constraints, params object[] args)
|
||||
{
|
||||
this.PopulateInternal(null, string.Format(constraints, args));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public dynamic PopulateWith(string fields)
|
||||
{
|
||||
this.PopulateInternal(fields, null);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public dynamic PopulateWith(string fields, string constraints, params object[] args)
|
||||
{
|
||||
this.PopulateInternal(fields, string.Format(constraints, args));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public dynamic PopulateFree(string query)
|
||||
{
|
||||
this.PopulateInternalFree(query);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public IEnumerator<Datum> GetEnumerator()
|
||||
{
|
||||
foreach (Datum loopDatum in this.Values)
|
||||
{
|
||||
yield return loopDatum;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return (IEnumerator)this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
public class Datum : DynamicObject
|
||||
{
|
||||
public string Table { get; private set; }
|
||||
|
||||
internal Dictionary<string, object> Dictionary { get; set; }
|
||||
|
||||
public Datum(string table)
|
||||
{
|
||||
this.Table = table;
|
||||
this.Dictionary = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
internal Datum(string table, Dictionary<string, object> values)
|
||||
{
|
||||
this.Table = table;
|
||||
this.Dictionary = values;
|
||||
}
|
||||
|
||||
internal void Populate(string query)
|
||||
{
|
||||
using (MySqlDataReader reader = MySqlHelper.ExecuteReader(Database.ConnectionString, query))
|
||||
{
|
||||
if (reader.RecordsAffected > 1)
|
||||
{
|
||||
throw new RowNotUniqueException();
|
||||
}
|
||||
|
||||
if (!reader.HasRows)
|
||||
{
|
||||
throw new RowNotInTableException();
|
||||
}
|
||||
|
||||
reader.Read();
|
||||
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
string name = reader.GetName(i);
|
||||
object value = reader.GetValue(i);
|
||||
|
||||
if (this.Dictionary.ContainsKey(name))
|
||||
{
|
||||
this.Dictionary[name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Dictionary.Add(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public dynamic Populate(string constraints, params object[] args)
|
||||
{
|
||||
this.Populate(string.Format("SELECT * FROM {0} WHERE {1}", this.Table, string.Format(constraints, args)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public dynamic PopulateWith(string fields, string constraints, params object[] args)
|
||||
{
|
||||
this.Populate(string.Format("SELECT {0} FROM {1} WHERE {2}", Database.CorrectFields(fields), this.Table, string.Format(constraints, args)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Insert()
|
||||
{
|
||||
string fields = "( ";
|
||||
|
||||
int processed = 0;
|
||||
|
||||
foreach (KeyValuePair<string, object> loopPair in this.Dictionary)
|
||||
{
|
||||
fields += loopPair.Key;
|
||||
processed++;
|
||||
|
||||
if (processed < this.Dictionary.Count)
|
||||
{
|
||||
fields += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
fields += " ) VALUES ( ";
|
||||
|
||||
processed = 0;
|
||||
|
||||
foreach (KeyValuePair<string, object> loopPair in this.Dictionary)
|
||||
{
|
||||
fields += string.Format("'{0}'", loopPair.Value is bool ? (((bool)loopPair.Value) ? 1 : 0) : loopPair.Value);
|
||||
processed++;
|
||||
|
||||
if (processed < this.Dictionary.Count)
|
||||
{
|
||||
fields += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
fields += " )";
|
||||
|
||||
Database.Execute("INSERT INTO {0} {1}", this.Table, fields);
|
||||
}
|
||||
|
||||
public void Update(string constraints, params object[] args)
|
||||
{
|
||||
int processed = 0;
|
||||
|
||||
string fields = string.Empty;
|
||||
|
||||
foreach (KeyValuePair<string, object> loopPair in this.Dictionary)
|
||||
{
|
||||
fields += string.Format("{0}='{1}'", loopPair.Key, loopPair.Value is bool ? (((bool)loopPair.Value) ? 1 : 0) : loopPair.Value);
|
||||
processed++;
|
||||
|
||||
if (processed < this.Dictionary.Count)
|
||||
{
|
||||
fields += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
Database.Execute("UPDATE {0} SET {1} WHERE {2}", this.Table, fields, string.Format(constraints, args));
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
if (this.Dictionary.ContainsKey(binder.Name))
|
||||
{
|
||||
if (this.Dictionary[binder.Name] is DBNull)
|
||||
{
|
||||
result = null;
|
||||
}
|
||||
else if (this.Dictionary[binder.Name] is byte && Meta.IsBool(this.Table, binder.Name))
|
||||
{
|
||||
result = (byte)this.Dictionary[binder.Name] > 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = this.Dictionary[binder.Name];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = default(object);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||
{
|
||||
if (value is DateTime)
|
||||
{
|
||||
if (Meta.IsDate(this.Table, binder.Name))
|
||||
{
|
||||
value = ((DateTime)value).ToString("yyyy-MM-dd");
|
||||
}
|
||||
else if (Meta.IsDateTime(this.Table, binder.Name))
|
||||
{
|
||||
value = ((DateTime)value).ToString("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
if (this.Dictionary.ContainsKey(binder.Name))
|
||||
{
|
||||
this.Dictionary[binder.Name] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Dictionary.Add(binder.Name, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result = this.Table + " [ ";
|
||||
|
||||
int processed = 0;
|
||||
|
||||
foreach (KeyValuePair<string, object> value in this.Dictionary)
|
||||
{
|
||||
result += value.Key;
|
||||
processed++;
|
||||
|
||||
if (processed < this.Dictionary.Count)
|
||||
{
|
||||
result += ", ";
|
||||
}
|
||||
}
|
||||
|
||||
result += " ]";
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
trunk/Common/Data/Meta.cs
Normal file
70
trunk/Common/Data/Meta.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace KartExtreme.Data
|
||||
{
|
||||
internal static class Meta
|
||||
{
|
||||
public static Dictionary<string, Dictionary<string, Column>> Tables = new Dictionary<string, Dictionary<string, Column>>();
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
Meta.Tables.Clear();
|
||||
|
||||
foreach (dynamic datum in new Datums("COLUMNS").Populate("TABLE_SCHEMA = '{0}'", Database.DefaultSchema))
|
||||
{
|
||||
Meta.Add(datum);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Add(dynamic datum)
|
||||
{
|
||||
Dictionary<string, Column> table;
|
||||
|
||||
string tableName = datum.TABLE_NAME;
|
||||
|
||||
if (Meta.Tables.ContainsKey(tableName))
|
||||
{
|
||||
table = Meta.Tables[tableName];
|
||||
}
|
||||
else
|
||||
{
|
||||
table = new Dictionary<string, Column>();
|
||||
Meta.Tables.Add(tableName, table);
|
||||
}
|
||||
|
||||
table.Add(datum.COLUMN_NAME, new Column(datum));
|
||||
}
|
||||
|
||||
public static bool IsBool(String tableName, String fieldName)
|
||||
{
|
||||
return Meta.Tables[tableName][fieldName].ColumnType == "tinyint(1) unsigned";
|
||||
}
|
||||
|
||||
public static bool IsDate(String tableName, String fieldName)
|
||||
{
|
||||
return Meta.Tables[tableName][fieldName].ColumnType == "date";
|
||||
}
|
||||
|
||||
public static bool IsDateTime(String tableName, String fieldName)
|
||||
{
|
||||
return Meta.Tables[tableName][fieldName].ColumnType == "datetime";
|
||||
}
|
||||
}
|
||||
|
||||
internal class Column
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
public bool IsPrimaryKey { get; private set; }
|
||||
public bool IsUniqueKey { get; private set; }
|
||||
public string ColumnType { get; private set; }
|
||||
|
||||
public Column(dynamic datum)
|
||||
{
|
||||
this.Name = datum.COLUMN_NAME;
|
||||
this.IsPrimaryKey = datum.COLUMN_KEY == "PRI";
|
||||
this.IsUniqueKey = datum.COLUMN_KEY == "UNI";
|
||||
this.ColumnType = datum.COLUMN_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
trunk/Common/Data/RowNotUniqueException.cs
Normal file
13
trunk/Common/Data/RowNotUniqueException.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace System.Data
|
||||
{
|
||||
public class RowNotUniqueException : DataException
|
||||
{
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Obtained row is not unique.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user