using System; using System.Collections.Generic; using System.Data; namespace TShockAPI.DB { public static class DbExt { /// /// Executes a query on a database. /// /// Database to query /// Query string with parameters as @0, @1, etc. /// Parameters to be put in the query /// Rows affected by query public static int Query(this IDbConnection olddb, string query, params object[] args) { using (var db = olddb.CloneEx()) { db.Open(); using (var com = db.CreateCommand()) { com.CommandText = query; for (int i = 0; i < args.Length; i++) com.AddParameter("@" + i, args[i]); return com.ExecuteNonQuery(); } } } /// /// Executes a query on a database. /// /// Database to query /// Query string with parameters as @0, @1, etc. /// Parameters to be put in the query /// Query result as IDataReader public static QueryResult QueryReader(this IDbConnection olddb, string query, params object[] args) { var db = olddb.CloneEx(); db.Open(); using (var com = db.CreateCommand()) { com.CommandText = query; for (int i = 0; i < args.Length; i++) com.AddParameter("@" + i, args[i]); return new QueryResult(db, com.ExecuteReader()); } } public static IDbDataParameter AddParameter(this IDbCommand command, string name, object data) { var parm = command.CreateParameter(); parm.ParameterName = name; parm.Value = data; command.Parameters.Add(parm); return parm; } public static IDbConnection CloneEx(this IDbConnection conn) { var clone = (IDbConnection)Activator.CreateInstance(conn.GetType()); clone.ConnectionString = conn.ConnectionString; return clone; } public static SqlType GetSqlType(this IDbConnection conn) { var name = conn.GetType().Name; if (name == "SqliteConnection") return SqlType.Sqlite; if (name == "MySqlConnection") return SqlType.Mysql; return SqlType.Unknown; } static readonly Dictionary> ReadFuncs = new Dictionary>() { {typeof(bool), (s, i) => s.GetBoolean(i)}, {typeof(byte), (s, i) => s.GetByte(i)}, {typeof(Int16), (s, i) => s.GetInt16(i)}, {typeof(Int32), (s, i) => s.GetInt32(i)}, {typeof(Int64), (s, i) => s.GetInt64(i)}, {typeof(string), (s, i) => s.GetString(i)}, {typeof(decimal), (s, i) => s.GetDecimal(i)}, {typeof(float), (s, i) => s.GetFloat(i)}, {typeof(double), (s, i) => s.GetDouble(i)}, {typeof(object), (s, i) => s.GetValue(i)}, }; public static T Get(this IDataReader reader, string column) { return reader.Get(reader.GetOrdinal(column)); } public static T Get(this IDataReader reader, int column) { if (reader.IsDBNull(column)) return default(T); if (ReadFuncs.ContainsKey(typeof(T))) return (T)ReadFuncs[typeof(T)](reader, column); throw new NotImplementedException(); } } public enum SqlType { Unknown, Sqlite, Mysql } public class QueryResult : IDisposable { public IDbConnection Connection { get; protected set; } public IDataReader Reader { get; protected set; } public QueryResult(IDbConnection conn, IDataReader reader) { Connection = conn; Reader = reader; } public void Dispose() { Reader.Dispose(); Connection.Dispose(); } public bool Read() { return Reader.Read(); } public T Get(string column) { return Reader.Get(Reader.GetOrdinal(column)); } } }