diff --git a/Database-Attribute_System/Function.cs b/Database-Attribute_System/Function.cs index 31d124f..edf87cb 100644 --- a/Database-Attribute_System/Function.cs +++ b/Database-Attribute_System/Function.cs @@ -1,5 +1,7 @@ -using System; +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 @@ -16,5 +18,69 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System { return dt.ToString("yyyy-MM-dd HH:mm:ss"); } + + + public static object[] BuildKeyEqualQuery(Dictionary keysets, string seperator) + { + object[] param = new object[keysets.Count * 2]; + int c = 0; + foreach (KeyValuePair keyset in keysets) + { + string sql_string = ""; + + if (c != 0) sql_string += seperator; + sql_string += $"{keyset.Key}="; + + param[c] = sql_string; + param[c + 1] = keyset.Value; + + c += 2; + } + + return param; + } + + 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'"); + 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) + { + Type classType = T.GetType(); + + // Reset lists (just in case) + dbPrimaryKeys = new Dictionary () { }; + dbAttributes = new Dictionary() { }; + dbForeignKeys = new Dictionary() { }; + + // Iterate thru all properties + foreach (System.Reflection.FieldInfo fi in classType.GetRuntimeFields()) + { + // Check if current field is a db-field + if (fi.GetCustomAttribute(typeof(DbPrimaryKey), true) is DbPrimaryKey pkey) // PrimaryKey + { + string dbAttributeName = pkey._attributeName ?? fi.Name; // If no alternative attribute-name is specified, use the property-name + object value = fi.GetValue(classObject); + dbPrimaryKeys.Add(dbAttributeName, value); + } + else if (fi.GetCustomAttribute(typeof(DbAttribute), true) is DbAttribute att) // Attributes + { + string dbAttributeName = att._attributeName ?? fi.Name; // If no alternative attribute-name is specified, use the property-name + object value = fi.GetValue(classObject); + dbAttributes.Add(dbAttributeName, value); + } + else if (fi.GetCustomAttribute(typeof(DbForeignKey), true) is DbForeignKey fkey) // ForeignKeys + { + string dbAttributeName = fkey._attributeName ?? fi.Name; // If no alternative attribute-name is specified, use the property-name + object value = fi.GetValue(classObject); + dbForeignKeys.Add(dbAttributeName, value); + } + } + } } } diff --git a/Database-Attribute_System/QueryBuilder.cs b/Database-Attribute_System/QueryBuilder.cs index 690d0ea..79af8f9 100644 --- a/Database-Attribute_System/QueryBuilder.cs +++ b/Database-Attribute_System/QueryBuilder.cs @@ -7,59 +7,86 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System { public class QueryBuilder { - /// - /// Build an SELECT-SQL-query by a database-primary-key - /// Will build the query-string based on the including serialising and escaping for SQL. - /// - /// Method to send querys to the database - /// Database comparison value - /// Built SQL-Query - public static string SelectByPrimaryKey(Type classType, object comparisonValue) => SelectByPrimaryKeys(classType, comparisonValue); - /// - /// Build an SELECT-SQL-query by database-primary-keys - /// Will build the query-string based on the including serialising and escaping for SQL. - /// - /// Method to send querys to the database - /// Database comparison values (Must be the exact same amount as primary keys in class/table) - /// Built SQL-Query - public static string SelectByPrimaryKeys(Type classType, params object[] comparisonValues) + public static string SelectByPrimaryKeys(T classObject) + { + Type classType = classObject.GetType(); + + // Get db-table-name from class + string tableName = Function.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); + + // Build where statements with primaryKey/s + object[] param = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + // Add SQL-command part + param[0] += $"SELECT * FROM {tableName} WHERE "; + + // Build and return the query + return BuildQuery(param); + } + + + public static string UpdateByPrimaryKeys(T classObject) { - // 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'"); - string tableName = dbObjectAttribute._tableName ?? classType.Name; // If no alternative table-name is specified, use the class-name + Type classType = classObject.GetType(); - // Iterate thru all properties - List dbPrimaryKeys = new List() { }; - foreach (System.Reflection.FieldInfo fi in classType.GetRuntimeFields()) + // Get db-table-name from class + string tableName = Function.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); + + // Add foreign-keys to attributes + foreach(KeyValuePair dbForeignKey in dbForeignKeys) { - // Get primaryKey attribute from current property - if (fi.GetCustomAttribute(typeof(DbPrimaryKey), true) is DbPrimaryKey pkey) - { - string dbAttributeName = pkey._attributeName ?? fi.Name; // If no alternative attribute-name is specified, use the property-name - dbPrimaryKeys.Add(dbAttributeName); - } + dbAttributes.Add(dbForeignKey.Key, dbForeignKey.Value); } - if (comparisonValues.Length != dbPrimaryKeys.Count) throw new InvalidOperationException("Primary-key number of class/table and number of comparison values is not equal!"); + // Build set-parameters + object[] paramSet = Function.BuildKeyEqualQuery(dbAttributes, ", "); + // Add SQL-command part + paramSet[0] += $"UPDATE {tableName} SET "; + // Build where-parameters + object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + // Add SQL-command part + paramWhere[0] += " WHERE "; - object[] param = new object[comparisonValues.Length * 2]; - for (int i = 0, c = 0; c < param.Length; i++, c += 2) - { - string sql_string = ""; + // Build and return the query + return BuildQuery(paramSet, paramWhere); + } - if (i == 0) sql_string += $"SELECT * FROM {tableName} WHERE "; - else sql_string += " AND "; - sql_string += $"{dbPrimaryKeys[i]}="; + public static string DeleteByPrimaryKeys(T classObject) + { + Type classType = classObject.GetType(); - param[c] = sql_string; - param[c + 1] = comparisonValues[i]; - } + // Get db-table-name from class + string tableName = Function.GetDbTableName(classType); - return BuildQuery(param); + // 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); + + // Build where-parameters + object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); + // Add SQL-command part + paramWhere[0] += $"DELETE FROM {tableName} WHERE "; + + // Build and return the query + return BuildQuery(paramWhere); } + /// /// Build an SQL-query /// Will build the query-string based on the s including serialising and escaping for SQL.