From 47e396b8027a35c95ef40cb331a1004e0982a9c5 Mon Sep 17 00:00:00 2001 From: Railz Date: Thu, 28 Mar 2019 11:37:02 +0100 Subject: [PATCH] Added QueryBuilder > Added build for SelectByPrimaryKey/s Added Attributes Added Function > SqlSerialise and escape --- .../Attributes/DbAttribute.cs | 22 ++++ .../Attributes/DbForeignKey.cs | 25 ++++ .../Attributes/DbObject.cs | 24 ++++ .../Attributes/DbPrimaryKey.cs | 23 ++++ Database-Attribute_System/Class1.cs | 8 -- Database-Attribute_System/Function.cs | 20 +++ Database-Attribute_System/QueryBuilder.cs | 115 ++++++++++++++++++ 7 files changed, 229 insertions(+), 8 deletions(-) create mode 100644 Database-Attribute_System/Attributes/DbAttribute.cs create mode 100644 Database-Attribute_System/Attributes/DbForeignKey.cs create mode 100644 Database-Attribute_System/Attributes/DbObject.cs create mode 100644 Database-Attribute_System/Attributes/DbPrimaryKey.cs delete mode 100644 Database-Attribute_System/Class1.cs create mode 100644 Database-Attribute_System/Function.cs create mode 100644 Database-Attribute_System/QueryBuilder.cs diff --git a/Database-Attribute_System/Attributes/DbAttribute.cs b/Database-Attribute_System/Attributes/DbAttribute.cs new file mode 100644 index 0000000..ec79b91 --- /dev/null +++ b/Database-Attribute_System/Attributes/DbAttribute.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes +{ + [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public class DbAttribute : Attribute + { + public string _attributeName; + + /// + /// 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) + { + this._attributeName = attributeName; + } + } +} diff --git a/Database-Attribute_System/Attributes/DbForeignKey.cs b/Database-Attribute_System/Attributes/DbForeignKey.cs new file mode 100644 index 0000000..a7df3dd --- /dev/null +++ b/Database-Attribute_System/Attributes/DbForeignKey.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes +{ + [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public class DbForeignKey : Attribute + { + public Type _classType; + public string _attributeName; + + /// + /// 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) + { + this._classType = classType; + this._attributeName = attributeName; + } + } +} diff --git a/Database-Attribute_System/Attributes/DbObject.cs b/Database-Attribute_System/Attributes/DbObject.cs new file mode 100644 index 0000000..04d511b --- /dev/null +++ b/Database-Attribute_System/Attributes/DbObject.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; + +namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes +{ + [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] + public class DbObject : Attribute + { + public string _tableName; + + /// + /// Marks variable as database-table + /// + /// 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; + } + } +} diff --git a/Database-Attribute_System/Attributes/DbPrimaryKey.cs b/Database-Attribute_System/Attributes/DbPrimaryKey.cs new file mode 100644 index 0000000..3769dd1 --- /dev/null +++ b/Database-Attribute_System/Attributes/DbPrimaryKey.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes +{ + [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] + public class DbPrimaryKey : Attribute + { + public Type _classType; + public string _attributeName; + + /// + /// Marks variable as primaryKey fo current class + /// + /// 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; + } + } +} diff --git a/Database-Attribute_System/Class1.cs b/Database-Attribute_System/Class1.cs deleted file mode 100644 index aa3b29a..0000000 --- a/Database-Attribute_System/Class1.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; - -namespace eu.railduction.netcore.dll.Database_Attribute_System -{ - public class Class1 - { - } -} diff --git a/Database-Attribute_System/Function.cs b/Database-Attribute_System/Function.cs new file mode 100644 index 0000000..31d124f --- /dev/null +++ b/Database-Attribute_System/Function.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace eu.railduction.netcore.dll.Database_Attribute_System +{ + class Function + { + 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"); + } + } +} diff --git a/Database-Attribute_System/QueryBuilder.cs b/Database-Attribute_System/QueryBuilder.cs new file mode 100644 index 0000000..5ee0e4f --- /dev/null +++ b/Database-Attribute_System/QueryBuilder.cs @@ -0,0 +1,115 @@ +using eu.railduction.netcore.dll.Database_Attribute_System.Attributes; +using System; +using System.Collections.Generic; +using System.Reflection; + +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) + { + // Check if class has attribute 'DbObject' and get the database table-name + DbObject dbObjectAttribute = classType.GetCustomAttribute(typeof(DbObject), true) as DbObject; + if (dbObjectAttribute == null) throw new InvalidOperationException("Cannot generate SQL-Query of class. Missing Attribute 'DbObject'"); + string tableName = dbObjectAttribute._tableName ?? dbObjectAttribute._tableName; // If no alternative table-name is specified, use the class-name + + // Iterate thru all properties + List dbPrimaryKeys = new List() { }; + foreach (System.Reflection.PropertyInfo pi in classType.GetProperties()) + { + // Get primaryKey attribute from current property + DbPrimaryKey pkey = pi.GetCustomAttribute(typeof(DbPrimaryKey) ,true) as DbPrimaryKey; + if(pkey != null) + { + string dbAttributeName = pkey._attributeName ?? pi.Name; // If no alternative attribute-name is specified, use the property-name + dbPrimaryKeys.Add(dbAttributeName); + } + } + + if (comparisonValues.Length != dbPrimaryKeys.Count) + throw new InvalidOperationException("Primary-key number of class/table and number of comparison values is not equal!"); + + object[] whereParams = new object[comparisonValues.Length*2]; + for (int i=0,c=0; c 0) sql_string += " AND "; + sql_string += $"{dbPrimaryKeys[i]}="; + + whereParams[c] = sql_string; + whereParams[c+1] = comparisonValues[i]; + } + + return BuildQuery($"SELECT * FROM {tableName} WHERE ", whereParams); + } + + + /// + /// Build an SQL-query + /// Will build the query-string based on the s including serialising and escaping for SQL. + /// + /// Params with alternating query-parts and objects beginning with a query-part + /// Example: "SELECT * FROM table WHERE id=", id, " AND name=", name + public static string BuildQuery(params object[] param) + { + string query = ""; + for (int i = 0; i < param.Length; i++) + { + if (i % 2 == 0) query += param[i]; // Every 'even' count will just add + else // Every 'uneven' count will handle param as passed variable + { + string paramString = ""; + if (param[i] == null) // Handle null + { + paramString = "null"; + } + else if (param[i].GetType() == typeof(string)) // Handle strings + { + paramString = "'" + Function.SqlEscape((string)param[i]) + "'"; // wrap in sql-brackets and escape sql, if any + } + else if (param[i].GetType() == typeof(int) || param[i].GetType() == typeof(float) || param[i].GetType() == typeof(double)) // Handle int, float & double + { + paramString = param[i].ToString().Replace(",", "."); // just format to string and form comma to sql-comma + } + else if (param[i].GetType() == typeof(DateTime)) // Handle DateTime + { + DateTime dateTime = (DateTime)param[i]; + paramString = "'" + Function.SqlSerialise(dateTime) + "'"; // wrap in sql-brackets and convert to sql-datetime + } + else if (param[i].GetType() == typeof(Guid)) // Handle DateTime + { + string guid = ((Guid)param[i]).ToString(); // Get Guid as string + paramString = "'" + guid + "'"; // wrap in sql-brackets + } + else // Unknown type in params + { + throw new Exception($"Error in query-builder: Type '{param.GetType().ToString()}' cannot be used!"); + } + + // Add formed param to query + query += paramString; + } + } + + // return built query + return query; + } + } +}