From 83dc8d6045d5d40022f7995284fbc643a7756efe Mon Sep 17 00:00:00 2001 From: Railz Date: Mon, 8 Apr 2019 22:21:48 +0200 Subject: [PATCH] Added foreignKeyFieldName for foreignKeys Added ResolveForeignKeys to ClassActions Changed ResolveByPrimaryKey to GetByPrimaryKey Added todo's --- .../Attributes/DbAttribute.cs | 2 +- .../Attributes/DbForeignKey.cs | 22 ++++++- .../Attributes/DbObject.cs | 2 +- .../Attributes/DbPrimaryKey.cs | 2 +- Database-Attribute_System/ClassAction.cs | 59 ++++++++++++++++--- 5 files changed, 73 insertions(+), 14 deletions(-) diff --git a/Database-Attribute_System/Attributes/DbAttribute.cs b/Database-Attribute_System/Attributes/DbAttribute.cs index 0c6e48c..b3889c8 100644 --- a/Database-Attribute_System/Attributes/DbAttribute.cs +++ b/Database-Attribute_System/Attributes/DbAttribute.cs @@ -16,7 +16,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes /// Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name] public DbAttribute(string attributeName = null) { - this._attributeName = attributeName; + this._attributeName = attributeName; // Todo: Automatic resolving of name if it is null (?) } } } diff --git a/Database-Attribute_System/Attributes/DbForeignKey.cs b/Database-Attribute_System/Attributes/DbForeignKey.cs index a7df3dd..156daa0 100644 --- a/Database-Attribute_System/Attributes/DbForeignKey.cs +++ b/Database-Attribute_System/Attributes/DbForeignKey.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Threading.Tasks; namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes @@ -10,16 +11,33 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes { public Type _classType; public string _attributeName; + public string _foreignKeyFieldName; + public FieldInfo _foreignKeyField; /// /// Marks variable as foreignKey of given class /// /// Type of class to which this is the ForeignKey /// Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name] - public DbForeignKey(Type classType, string attributeName = null) + /// Name of foreignKey-fieldName ['null' if the same as classType-name] + public DbForeignKey(Type classType, string foreignKeyFieldName = null, string attributeName = null) { this._classType = classType; - this._attributeName = attributeName; + this._attributeName = attributeName; // Todo: Automatic resolving of name if it is null (?) + + bool fieldFound = false; + foreach (System.Reflection.FieldInfo fi in classType.GetRuntimeFields()) + { + if(fi.Name.ToLower() == foreignKeyFieldName.ToLower()) + { + this._foreignKeyFieldName = fi.Name; + this._foreignKeyField = fi; + + fieldFound = true; + break; + } + } + if (!fieldFound) throw new InvalidOperationException($"Field with name='{foreignKeyFieldName}' not found in {classType.Name}."); } } } diff --git a/Database-Attribute_System/Attributes/DbObject.cs b/Database-Attribute_System/Attributes/DbObject.cs index 04d511b..06eaa4d 100644 --- a/Database-Attribute_System/Attributes/DbObject.cs +++ b/Database-Attribute_System/Attributes/DbObject.cs @@ -18,7 +18,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes /// Name of database-table (case-sensitivity is determined from database-table-settings) ['null' if the same as class-name] public DbObject(string tableName = null) { - this._tableName = tableName; + this._tableName = tableName; // Todo: Automatic resolving of name if it is null (?) } } } diff --git a/Database-Attribute_System/Attributes/DbPrimaryKey.cs b/Database-Attribute_System/Attributes/DbPrimaryKey.cs index 3769dd1..ba4b473 100644 --- a/Database-Attribute_System/Attributes/DbPrimaryKey.cs +++ b/Database-Attribute_System/Attributes/DbPrimaryKey.cs @@ -17,7 +17,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes /// Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name] public DbPrimaryKey(string attributeName = null) { - this._attributeName = attributeName; + this._attributeName = attributeName; // Todo: Automatic resolving of name if it is null (?) } } } diff --git a/Database-Attribute_System/ClassAction.cs b/Database-Attribute_System/ClassAction.cs index 0aee916..c0c2251 100644 --- a/Database-Attribute_System/ClassAction.cs +++ b/Database-Attribute_System/ClassAction.cs @@ -1,4 +1,5 @@ -using System; +using eu.railduction.netcore.dll.Database_Attribute_System.Attributes; +using System; using System.Collections.Generic; using System.Reflection; using System.Text; @@ -72,21 +73,21 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System /// - /// Resolves an object with the database - /// Needs to have primaryKey/s-value/s set! - /// - Generates an query - /// - Sends an query via Func - /// - Fills the object with data + /// Gets an dbObject /// /// /// Given object (marked with Db-attributes) /// Function to handle query-calls - Has to return Dictionary[attributeName, attributeValue] /// This checks if any class-field and data-attribute does not exists in either (Slower) - public static void ResolveByPrimaryKey(T classObject, Func>> queryExecutor, bool runDataLossChecks = true) + public static T GetByPrimaryKey(Type classType, Func>> queryExecutor, bool runDataLossChecks = true) where T: new() { - string query = QueryBuilder.SelectByPrimaryKey(classObject); // Generate query + T obj = new T(); + + string query = QueryBuilder.SelectByPrimaryKey(obj); // Generate query List> dataSet = queryExecutor(query); // Execute - FillObject(classObject, dataSet[0], runDataLossChecks); // Fill the object + FillObject(obj, dataSet[0], runDataLossChecks); // Fill the object + + return obj; } /// @@ -117,5 +118,45 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System return objs; // Return list } + + + + /// + /// Resolves all foreignKeys with the database + /// + /// + /// Given object (marked with Db-attributes) + /// Function to handle query-calls - Has to return Dictionary[attributeName, attributeValue] + /// Determents how deep resolving will be executed + /// This checks if any class-field and data-attribute does not exists in either (Slower) + public static void ResolveForeignKeys(T classObject, Func>> queryExecutor, int max_depth = 1, bool runDataLossChecks = true) where T: new() + { + Type classType = classObject.GetType(); + + // Get class-fields + Dictionary dbFields = Function.ReadDbClassFields(classType); + + foreach (KeyValuePair dbField in dbFields) + { + // If field is foreignKey + if (dbField.Value.GetCustomAttribute(typeof(DbForeignKey), true) is DbForeignKey fkey) + { + FieldInfo f_Field = fkey._foreignKeyField; + object f_value = f_Field.GetValue(classObject); + + // When its empty, get it + if(f_value == null) + { + f_value = GetByPrimaryKey(classType, queryExecutor, runDataLossChecks); ; + } + + // Recursive resolving + if (max_depth - 1 > 0) + { + ResolveForeignKeys(f_value, queryExecutor, max_depth - 1, runDataLossChecks); + } + } + } + } } }