11 Commits
v1.1 ... v1.2.2

Author SHA1 Message Date
Railz
d8c9867e50 Set version 2019-04-08 13:54:24 +02:00
Railz
166956f10f Added SelectByAttribute and DeleteByAttribute to QueryBuilder 2019-04-08 13:49:11 +02:00
Alexander B
ddb7f6dc89 Fixed ResolveByPrimaryKey - queryExecutor to be able to return multiple rows (via List) 2019-04-02 13:31:26 +02:00
Alexander B
06aa7969bf Removed unesserary variable 2019-04-02 09:49:04 +02:00
Railz
fb6cf14402 Fixed ResolveByPrimaryKey not having runDataLossChecks implemented 2019-04-01 18:52:38 +02:00
Railz
e8e1fb993d Removed ignoreDataMismatch and implemented runDataLossChecks instead 2019-04-01 18:49:37 +02:00
Railz
8633ac1925 Changed wrong comment 2019-04-01 18:38:44 +02:00
Railz
8de75728e0 Fixed ClassAction not being public
Moved SqlSerialise to Function
2019-04-01 18:33:53 +02:00
Railz
0f38c92bbe Added ResolveByPrimaryKey 2019-04-01 17:33:16 +02:00
Railz
46e8ec1180 New Function-class
Changed some references to new Function-class
Added ClassAction.FillObject
Added ClassAction.FillObject
Renamed unecessary plural names to singular
2019-04-01 17:26:30 +02:00
Railz
97b7eaeffe Added comments
Added check if given class is invalid
Changed BuildQuery to support recursive object[] copying
Changed structure
Added DbFunction to handle all Db-related stuff
2019-04-01 16:25:02 +02:00
7 changed files with 410 additions and 137 deletions

View File

@@ -14,7 +14,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes
/// Marks variable as database-attribute /// Marks variable as database-attribute
/// </summary> /// </summary>
/// <param name="dbAttributeName">Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name]</param> /// <param name="dbAttributeName">Name of database-attribute (case-sensitivity is determined from database-attribute-settings) ['null' if the same as field-name]</param>
public DbAttribute(string attributeName = null) public DbAttribute(string attributeName = null)
{ {
this._attributeName = attributeName; this._attributeName = attributeName;
} }

View File

@@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace eu.railduction.netcore.dll.Database_Attribute_System
{
public class ClassAction
{
/// <summary>
/// Fills an given dbObject with given data<para/>
/// Data-attribute-names and class-fieldNames have to match! (non case-sensitive)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <param name="data">The data</param>
/// <param name="runDataLossChecks">This checks if any class-field and data-attribute does not exists in either (Slower)</param>
public static void FillObject<T>(T classObject, Dictionary<string, object> data, bool runDataLossChecks = true)
{
Type classType = classObject.GetType();
string tableName = Function.GetDbTableName(classType);
// Get class-fields
Dictionary<string, FieldInfo> dbFields = Function.ReadDbClassFields(classObject);
if (runDataLossChecks)
{
// Check every data-attribute for match in class-fields
foreach (KeyValuePair<string, object> data_keySet in data)
{
bool isFound = false;
foreach (KeyValuePair<string, FieldInfo> field_keySet in dbFields)
{
if (field_keySet.Key.ToLower() == data_keySet.Key.ToLower())
isFound = true;
}
if (!isFound)
throw new InvalidOperationException($"Could not fill object. Data-Attribute '{data_keySet.Key}' was not found in class!");
}
// Check every class-field for match in data-attributes
foreach (KeyValuePair<string, FieldInfo> field_keySet in dbFields)
{
bool isFound = false;
foreach (KeyValuePair<string, object> data_keySet in data)
{
if (field_keySet.Key.ToLower() == data_keySet.Key.ToLower())
isFound = true;
}
if (!isFound)
throw new InvalidOperationException($"Could not fill object. Class-field '{field_keySet.Key}' was not found in data!");
}
}
// Iterate through data
foreach (KeyValuePair<string, object> data_keySet in data)
{
// Interate through class-fields
foreach (KeyValuePair<string, FieldInfo> field_keySet in dbFields)
{
// If its a match, set the value
if (field_keySet.Key.ToLower() == data_keySet.Key.ToLower())
{
field_keySet.Value.SetValue(classObject, data_keySet.Value);
break;
}
}
}
}
/// <summary>
/// Resolves an object with the database<para/>
/// Needs to have primaryKey/s set!<para/>
/// - Generates an query<para/>
/// - Sends an query via Func<para/>
/// - Fills the object with data
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <param name="queryExecutor">Function to handle query-calls - Has to return Dictionary[attributeName, attributeValue]</param>
/// <param name="runDataLossChecks">This checks if any class-field and data-attribute does not exists in either (Slower)</param>
public static void ResolveByPrimaryKey<T>(T classObject, Func<string, List<Dictionary<string, object>>> queryExecutor, bool runDataLossChecks = true)
{
string query = QueryBuilder.SelectByPrimaryKey(classObject);
List<Dictionary<string, object>> dataSet = queryExecutor(query);
FillObject(classObject, dataSet[0], runDataLossChecks);
}
}
}

View File

@@ -4,6 +4,7 @@
<TargetFramework>netcoreapp2.1</TargetFramework> <TargetFramework>netcoreapp2.1</TargetFramework>
<RootNamespace>eu.railduction.netcore.dll.Database_Attribute_System</RootNamespace> <RootNamespace>eu.railduction.netcore.dll.Database_Attribute_System</RootNamespace>
<SignAssembly>false</SignAssembly> <SignAssembly>false</SignAssembly>
<Version>1.2.3</Version>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@@ -1,86 +0,0 @@
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
{
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");
}
public static object[] BuildKeyEqualQuery(Dictionary<string, object> keysets, string seperator)
{
object[] param = new object[keysets.Count * 2];
int c = 0;
foreach (KeyValuePair<string, object> 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>(T classObject, ref Dictionary<string, object> dbPrimaryKeys, ref Dictionary<string, object> dbAttributes, ref Dictionary<string, object> dbForeignKeys)
{
Type classType = typeof(T);
// Reset lists (just in case)
dbPrimaryKeys = new Dictionary<string, object> () { };
dbAttributes = new Dictionary<string, object>() { };
dbForeignKeys = new Dictionary<string, object>() { };
// 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);
}
}
}
}
}

View File

@@ -7,7 +7,14 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
{ {
public class QueryBuilder public class QueryBuilder
{ {
public static string SelectByPrimaryKeys<T>(T classObject) /// <summary>
/// Builds an SELECT-Sql-query based on an object<para/>
/// Object needs to have at least 1 primary-key!
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <returns>SELECT-Sql-query</returns>
public static string SelectByPrimaryKey<T>(T classObject)
{ {
Type classType = classObject.GetType(); Type classType = classObject.GetType();
@@ -19,9 +26,10 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { }; Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { };
Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { }; Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { };
Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); Function.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 // Build where statements with primaryKey/s
object[] param = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); object[] param = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND ");
// Add SQL-command part // Add SQL-command part
param[0] = $"SELECT * FROM {tableName} WHERE "+ param[0]; param[0] = $"SELECT * FROM {tableName} WHERE "+ param[0];
@@ -29,8 +37,15 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
return BuildQuery(param); return BuildQuery(param);
} }
/// <summary>
public static string UpdateByPrimaryKeys<T>(T classObject) /// Builds an SELECT-Sql-query based on an object<para/>
/// Object needs to have at least 1 attribute!
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <param name="attributeNames">Attributes and/or foreignKeys to use in lookup</param>
/// <returns>SELECT-Sql-query</returns>
public static string SelectByAttribute<T>(T classObject, params string[] attributeNames)
{ {
Type classType = classObject.GetType(); Type classType = classObject.GetType();
@@ -42,20 +57,73 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { }; Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { };
Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { }; Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { };
Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys);
if (dbAttributes.Count == 0) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. No attribute found!");
Dictionary<string, object> attributes = new Dictionary<string, object>() { };
// Iterate through given names
foreach (string attributeName in attributeNames)
{
// Iterate through attributes of class
foreach (KeyValuePair<string, object> dbAttribute in dbAttributes)
{
// If its a match, copy it to list
if (dbAttribute.Key.ToLower() == attributeName.ToLower())
{
attributes.Add(dbAttribute.Key, dbAttribute.Value);
}
}
}
object[] param = new object[1];
if (attributeNames != null)
{
// Build where statements with primaryKey/s
param = DbFunction.BuildKeyEqualQuery(attributes, " AND ");
}
// Add SQL-command part
param[0] = $"SELECT * FROM {tableName} WHERE " + param[0];
// Build and return the query
return BuildQuery(param);
}
/// <summary>
/// Builds an UPDATE-Sql-query based on an object<para/>
/// Object needs to have at least 1 primary-key!
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <returns>UPDATE-Sql-query</returns>
public static string UpdateByPrimaryKey<T>(T classObject)
{
Type classType = classObject.GetType();
// Get db-table-name from class
string tableName = Function.GetDbTableName(classType);
// Get class db-fields
Dictionary<string, object> dbPrimaryKeys = new Dictionary<string, object>() { };
Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { };
Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { };
Function.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 // Add foreign-keys to attributes
foreach(KeyValuePair<string, object> dbForeignKey in dbForeignKeys) foreach (KeyValuePair<string, object> dbForeignKey in dbForeignKeys)
{ {
dbAttributes.Add(dbForeignKey.Key, dbForeignKey.Value); dbAttributes.Add(dbForeignKey.Key, dbForeignKey.Value);
} }
// Build set-parameters // Build set-parameters
object[] paramSet = Function.BuildKeyEqualQuery(dbAttributes, ", "); object[] paramSet = DbFunction.BuildKeyEqualQuery(dbAttributes, ", ");
// Add SQL-command part // Add SQL-command part
paramSet[0] = $"UPDATE {tableName} SET "+ paramSet[0]; paramSet[0] = $"UPDATE {tableName} SET "+ paramSet[0];
// Build where-parameters // Build where-parameters
object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); object[] paramWhere = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND ");
// Add SQL-command part // Add SQL-command part
paramWhere[0] = " WHERE "+ paramWhere[0]; paramWhere[0] = " WHERE "+ paramWhere[0];
@@ -63,7 +131,14 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
return BuildQuery(paramSet, paramWhere); return BuildQuery(paramSet, paramWhere);
} }
public static string DeleteByPrimaryKeys<T>(T classObject) /// <summary>
/// Builds an DELETE-Sql-query based on an object<para/>
/// Object needs to have at least 1 primary-key!
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <returns>DELETE-Sql-query</returns>
public static string DeleteByPrimaryKey<T>(T classObject)
{ {
Type classType = classObject.GetType(); Type classType = classObject.GetType();
@@ -75,9 +150,10 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { }; Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { };
Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { }; Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { };
Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys); Function.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 // Build where-parameters
object[] paramWhere = Function.BuildKeyEqualQuery(dbPrimaryKeys, " AND "); object[] paramWhere = DbFunction.BuildKeyEqualQuery(dbPrimaryKeys, " AND ");
// Add SQL-command part // Add SQL-command part
paramWhere[0] = $"DELETE FROM {tableName} WHERE "+ paramWhere[0]; paramWhere[0] = $"DELETE FROM {tableName} WHERE "+ paramWhere[0];
@@ -85,30 +161,75 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
return BuildQuery(paramWhere); return BuildQuery(paramWhere);
} }
/// <summary>
/// Builds an DELETE-Sql-query based on an object<para/>
/// Object needs to have at least 1 primary-key!
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="classObject">Given object (marked with Db-attributes)</param>
/// <param name="attributeNames">Attributes and/or foreignKeys to use in lookup</param>
/// <returns>DELETE-Sql-query</returns>
public static string DeleteByAttribute<T>(T classObject, params string[] attributeNames)
{
Type classType = classObject.GetType();
// Get db-table-name from class
string tableName = Function.GetDbTableName(classType);
// Get class db-fields
Dictionary<string, object> dbPrimaryKeys = new Dictionary<string, object>() { };
Dictionary<string, object> dbAttributes = new Dictionary<string, object>() { };
Dictionary<string, object> dbForeignKeys = new Dictionary<string, object>() { };
Function.ReadDbClassFields(classObject, ref dbPrimaryKeys, ref dbAttributes, ref dbForeignKeys);
if (dbAttributes.Count == 0) throw new InvalidOperationException($"Cannot generate SQL-Query of '{classType.Name}'. No attribute found!");
Dictionary<string, object> attributes = new Dictionary<string, object>() { };
// Iterate through given names
foreach (string attributeName in attributeNames)
{
// Iterate through attributes of class
foreach (KeyValuePair<string, object> dbAttribute in dbAttributes)
{
// If its a match, copy it to list
if (dbAttribute.Key.ToLower() == attributeName.ToLower())
{
attributes.Add(dbAttribute.Key, dbAttribute.Value);
}
}
}
object[] param = new object[1];
if (attributeNames != null)
{
// Build where statements with primaryKey/s
param = DbFunction.BuildKeyEqualQuery(attributes, " AND ");
}
// Add SQL-command part
param[0] = $"DELETE FROM {tableName} WHERE " + param[0];
// Build and return the query
return BuildQuery(param);
}
/// <summary> /// <summary>
/// Build an SQL-query<para/> /// Build an SQL-query<para/>
/// Will build the query-string based on the <paramref name="param"/>s including serialising and escaping for SQL.<para/> /// Will build the query-string based on the <paramref name="param"/>s including serialising and escaping for SQL.<para/>
/// (Supported-Types: null, string, byte, int, float, double, DateTime, Guid)
/// </summary> /// </summary>
/// <param name="param">Params with alternating query-parts and objects beginning with a query-part /// <param name="param">Params with alternating query-parts and objects beginning with a query-part
/// <para/>Example: "SELECT * FROM table WHERE id=", id, " AND name=", name</param> /// <para/>Example: "SELECT * FROM table WHERE id=", id, " AND name=", name<para/>
/// Info: Any object[] will be opened recursively and added as <paramref name="param"/> accordingly!
/// </param>
public static string BuildQuery(params object[] param) 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<object> paramz = new List<object>() { }; List<object> paramz = new List<object>() { };
foreach (object obj in param) Function.RecursiveParameterCopying(ref paramz, (object[])param);
{
if (!(obj is object[]))
paramz.Add(obj);
else
{
foreach (object obj2 in (object[])obj)
{
paramz.Add(obj2);
}
}
}
string query = ""; string query = "";
for (int i = 0; i < paramz.Count; i++) for (int i = 0; i < paramz.Count; i++)
@@ -116,33 +237,9 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
if (i % 2 == 0) query += paramz[i]; // Every 'even' count will just add if (i % 2 == 0) query += paramz[i]; // Every 'even' count will just add
else // Every 'uneven' count will handle param as passed variable else // Every 'uneven' count will handle param as passed variable
{ {
string paramString = ""; string paramString = Function.SqlSerialise(paramz[i]);
if (paramz[i] == null) // Handle null if(paramString == null) // Unknown type in params
{ throw new Exception($"Error in query-builder. Type '{paramz[i].GetType().ToString()}' cannot be serialised!");
paramString = "null";
}
else if (paramz[i].GetType() == typeof(string)) // Handle strings
{
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
{
paramString = paramz[i].ToString().Replace(",", "."); // just format to string and form comma to sql-comma
}
else if (paramz[i].GetType() == typeof(DateTime)) // Handle DateTime
{
DateTime dateTime = (DateTime)paramz[i];
paramString = "'" + Function.SqlSerialise(dateTime) + "'"; // wrap in sql-brackets and convert to sql-datetime
}
else if (paramz[i].GetType() == typeof(Guid)) // Handle DateTime
{
string guid = ((Guid)paramz[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 '{paramz[i].GetType().ToString()}' cannot be used!");
}
// Add formed param to query // Add formed param to query
query += paramString; query += paramString;

View File

@@ -0,0 +1,31 @@
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
{
class DbFunction
{
internal static object[] BuildKeyEqualQuery(Dictionary<string, object> keysets, string seperator)
{
object[] param = new object[keysets.Count * 2];
int c = 0;
foreach (KeyValuePair<string, object> 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;
}
}
}

View File

@@ -0,0 +1,138 @@
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<object> paramz, object[] objects)
{
foreach (object obj in objects)
{
if (!(obj is object[]))
paramz.Add(obj);
else
RecursiveParameterCopying(ref paramz, (object[])obj);
}
}
internal static void ReadDbClassFields<T>(T classObject, ref Dictionary<string, object> dbPrimaryKeys, ref Dictionary<string, object> dbAttributes, ref Dictionary<string, object> dbForeignKeys)
{
Type classType = typeof(T);
// Reset lists (just in case)
dbPrimaryKeys = new Dictionary<string, object>() { };
dbAttributes = new Dictionary<string, object>() { };
dbForeignKeys = new Dictionary<string, object>() { };
// 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);
}
}
}
internal static Dictionary<string, FieldInfo> ReadDbClassFields<T>(T classObject)
{
Type classType = typeof(T);
Dictionary<string, FieldInfo> dbFields = new Dictionary<string, FieldInfo>();
// 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
dbFields.Add(dbAttributeName, fi);
}
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
dbFields.Add(dbAttributeName, fi);
}
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
dbFields.Add(dbAttributeName, fi);
}
}
return dbFields;
}
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 '{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 string SqlSerialise(object obj)
{
if (obj == null) // Handle null
{
return "null";
}
else if (obj.GetType() == typeof(string)) // Handle strings
{
return "'" + SqlEscape((string)obj) + "'"; // wrap in sql-brackets and escape sql, if any
}
else if (obj.GetType() == typeof(byte) || obj.GetType() == typeof(int) || obj.GetType() == typeof(float) || obj.GetType() == typeof(double)) // Handle int, float & double
{
return obj.ToString().Replace(",", "."); // just format to string and form comma to sql-comma
}
else if (obj.GetType() == typeof(DateTime)) // Handle DateTime
{
DateTime dateTime = (DateTime)obj;
return "'" + SqlSerialise(dateTime) + "'"; // wrap in sql-brackets and convert to sql-datetime
}
else if (obj.GetType() == typeof(Guid)) // Handle DateTime
{
string guid = ((Guid)obj).ToString(); // Get Guid as string
return "'" + guid + "'"; // wrap in sql-brackets
}
else
{
return null;
}
}
}
}