diff --git a/Database-Attribute_System/Attributes/DbAttribute.cs b/Database-Attribute_System/Attributes/DbAttribute.cs index ec79b91..0c6e48c 100644 --- a/Database-Attribute_System/Attributes/DbAttribute.cs +++ b/Database-Attribute_System/Attributes/DbAttribute.cs @@ -14,7 +14,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes /// Marks variable as database-attribute /// /// Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name] - public DbAttribute(string attributeName = null) + public DbAttribute(string attributeName = null) { this._attributeName = attributeName; } diff --git a/Database-Attribute_System/QueryBuilder.cs b/Database-Attribute_System/QueryBuilder.cs index 1000b7d..f6d67c2 100644 --- a/Database-Attribute_System/QueryBuilder.cs +++ b/Database-Attribute_System/QueryBuilder.cs @@ -7,21 +7,29 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System { public class QueryBuilder { + /// + /// Builds an SELECT-Sql-query based on an object + /// Object needs to have at least 1 primary-key! + /// + /// + /// Given object (marked with Db-attributes) + /// SELECT-Sql-query public static string SelectByPrimaryKeys(T classObject) { Type classType = classObject.GetType(); // Get db-table-name from class - string tableName = Function.GetDbTableName(classType); + string tableName = DbFunction.GetDbTableName(classType); // Get class db-fields Dictionary dbPrimaryKeys = new Dictionary() { }; Dictionary dbAttributes = new Dictionary() { }; Dictionary dbForeignKeys = new Dictionary() { }; - Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + DbFunction.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + if (dbPrimaryKeys.Count == 0) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. No primary-key/s found!"); // Build where statements with primaryKey/s - object[] param = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + object[] param = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); // Add SQL-command part param[0] = $"SELECT * FROM {tableName} WHERE "+ param[0]; @@ -29,33 +37,40 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System return BuildQuery(param); } - + /// + /// Builds an UPDATE-Sql-query based on an object + /// Object needs to have at least 1 primary-key! + /// + /// + /// Given object (marked with Db-attributes) + /// UPDATE-Sql-query public static string UpdateByPrimaryKeys(T classObject) { Type classType = classObject.GetType(); // Get db-table-name from class - string tableName = Function.GetDbTableName(classType); + string tableName = DbFunction.GetDbTableName(classType); // Get class db-fields Dictionary dbPrimaryKeys = new Dictionary() { }; Dictionary dbAttributes = new Dictionary() { }; Dictionary dbForeignKeys = new Dictionary() { }; - Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + DbFunction.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + if (dbPrimaryKeys.Count == 0) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. No primary-key/s found!"); // Add foreign-keys to attributes - foreach(KeyValuePair dbForeignKey in dbForeignKeys) + foreach (KeyValuePair dbForeignKey in dbForeignKeys) { dbAttributes.Add(dbForeignKey.Key, dbForeignKey.Value); } // Build set-parameters - object[] paramSet = Function.BuildKeyEqualQuery(dbAttributes, ", "); + object[] paramSet = DbFunction.BuildKeyEqualQuery(dbAttributes, ", "); // Add SQL-command part paramSet[0] = $"UPDATE {tableName} SET "+ paramSet[0]; // Build where-parameters - object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + object[] paramWhere = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); // Add SQL-command part paramWhere[0] = " WHERE "+ paramWhere[0]; @@ -63,21 +78,29 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System return BuildQuery(paramSet, paramWhere); } + /// + /// Builds an DELETE-Sql-query based on an object + /// Object needs to have at least 1 primary-key! + /// + /// + /// Given object (marked with Db-attributes) + /// DELETE-Sql-query public static string DeleteByPrimaryKeys(T classObject) { Type classType = classObject.GetType(); // Get db-table-name from class - string tableName = Function.GetDbTableName(classType); + string tableName = DbFunction.GetDbTableName(classType); // Get class db-fields Dictionary dbPrimaryKeys = new Dictionary() { }; Dictionary dbAttributes = new Dictionary() { }; Dictionary dbForeignKeys = new Dictionary() { }; - Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + DbFunction.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); + if (dbPrimaryKeys.Count == 0) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. No primary-key/s found!"); // Build where-parameters - object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + object[] paramWhere = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); // Add SQL-command part paramWhere[0] = $"DELETE FROM {tableName} WHERE "+ paramWhere[0]; @@ -90,25 +113,17 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System /// /// Build an SQL-query /// Will build the query-string based on the s including serialising and escaping for SQL. + /// (Supported-Types: null, string, byte, int, float, double, DateTime, Guid) /// /// Params with alternating query-parts and objects beginning with a query-part - /// Example: "SELECT * FROM table WHERE id=", id, " AND name=", name + /// Example: "SELECT * FROM table WHERE id=", id, " AND name=", name + /// Info: Any object[] will be opened recursively and added as accordingly! + /// public static string BuildQuery(params object[] param) { - // Convert array to list and add object[] to it accordingly + // Convert array to list and add object[] to it recursively List paramz = new List() { }; - foreach (object obj in param) - { - if (!(obj is object[])) - paramz.Add(obj); - else - { - foreach (object obj2 in (object[])obj) - { - paramz.Add(obj2); - } - } - } + Function.RecursiveParameterCopying(ref paramz, (object[])param); string query = ""; for (int i = 0; i < paramz.Count; i++) @@ -125,7 +140,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System { paramString = "'" + Function.SqlEscape((string)paramz[i]) + "'"; // wrap in sql-brackets and escape sql, if any } - else if (paramz[i].GetType() == typeof(int) || paramz[i].GetType() == typeof(float) || paramz[i].GetType() == typeof(double)) // Handle int, float & double + else if (paramz[i].GetType() == typeof(byte) || paramz[i].GetType() == typeof(int) || paramz[i].GetType() == typeof(float) || paramz[i].GetType() == typeof(double)) // Handle int, float & double { paramString = paramz[i].ToString().Replace(",", "."); // just format to string and form comma to sql-comma } diff --git a/Database-Attribute_System/Function.cs b/Database-Attribute_System/internal/DbFunction.cs similarity index 79% rename from Database-Attribute_System/Function.cs rename to Database-Attribute_System/internal/DbFunction.cs index 61d6dc1..14ff831 100644 --- a/Database-Attribute_System/Function.cs +++ b/Database-Attribute_System/internal/DbFunction.cs @@ -6,21 +6,9 @@ using System.Text; namespace eu.railduction.netcore.dll.Database_Attribute_System { - class Function + class DbFunction { - public static string SqlEscape(string str) - { - string str_cpy = str.Replace(@"'", @"\'"); - return str_cpy; - } - - public static string SqlSerialise(DateTime dt) - { - return dt.ToString("yyyy-MM-dd HH:mm:ss"); - } - - - public static object[] BuildKeyEqualQuery(Dictionary keysets, string seperator) + internal static object[] BuildKeyEqualQuery(Dictionary keysets, string seperator) { object[] param = new object[keysets.Count * 2]; int c = 0; @@ -43,18 +31,18 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System public static string GetDbTableName(Type classType) { // Check if class has attribute 'DbObject' and get the database table-name - if (!(classType.GetCustomAttribute(typeof(DbObject), true) is DbObject dbObjectAttribute)) throw new InvalidOperationException("Cannot generate SQL-Query of class. Missing Attribute 'DbObject'"); + if (!(classType.GetCustomAttribute(typeof(DbObject), true) is DbObject dbObjectAttribute)) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. Missing Attribute 'DbObject'"); string tableName = dbObjectAttribute._tableName ?? classType.Name; // If no alternative table-name is specified, use the class-name return tableName; } - public static void ReadDbClassFields(T classObject, ref Dictionary dbPrimaryKeys, ref Dictionary dbAttributes, ref Dictionary dbForeignKeys) + internal static void ReadDbClassFields(T classObject, ref Dictionary dbPrimaryKeys, ref Dictionary dbAttributes, ref Dictionary dbForeignKeys) { Type classType = typeof(T); // Reset lists (just in case) - dbPrimaryKeys = new Dictionary () { }; + dbPrimaryKeys = new Dictionary() { }; dbAttributes = new Dictionary() { }; dbForeignKeys = new Dictionary() { }; diff --git a/Database-Attribute_System/internal/Function.cs b/Database-Attribute_System/internal/Function.cs new file mode 100644 index 0000000..b68fa05 --- /dev/null +++ b/Database-Attribute_System/internal/Function.cs @@ -0,0 +1,34 @@ +using eu.railduction.netcore.dll.Database_Attribute_System.Attributes; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace eu.railduction.netcore.dll.Database_Attribute_System +{ + internal class Function + { + public static string SqlEscape(string str) + { + string str_cpy = str.Replace(@"'", @"\'"); + return str_cpy; + } + + public static string SqlSerialise(DateTime dt, string format = "yyyy-MM-dd HH:mm:ss") + { + return dt.ToString(format); + } + + // Recursive object[] copying + internal static void RecursiveParameterCopying(ref List paramz, object[] objects) + { + foreach (object obj in objects) + { + if (!(obj is object[])) + paramz.Add(obj); + else + RecursiveParameterCopying(ref paramz, (object[])obj); + } + } + } +}