Added DbReverseForeignObject
Removed method SqlSerialise(DateTime ...)
This commit is contained in:
parent
aca99302dd
commit
111b3bf7ce
@ -20,6 +20,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes
|
||||
public List<DbAttribute> attributeAttributes = new List<DbAttribute>() { };
|
||||
public List<DbForeignKey> foreignKeyAttributes = new List<DbForeignKey>() { };
|
||||
public List<DbForeignObject> foreignObjectAttributes = new List<DbForeignObject>() { };
|
||||
public List<DbReverseForeignObject> reverseForeignObjectAttributes = new List<DbReverseForeignObject>() { };
|
||||
|
||||
/// <summary>
|
||||
/// Marks variable as database-table
|
||||
@ -68,6 +69,11 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System.Attributes
|
||||
|
||||
this.foreignObjectAttributes.Add(fobj);
|
||||
}
|
||||
else if (fi.GetCustomAttribute(typeof(DbReverseForeignObject), true) is DbReverseForeignObject rfobj) // ReverseForeignObjects
|
||||
{
|
||||
rfobj.Init(fi, this);
|
||||
this.reverseForeignObjectAttributes.Add(rfobj);
|
||||
}
|
||||
}
|
||||
catch(InvalidOperationException ex)
|
||||
{
|
||||
|
@ -0,0 +1,60 @@
|
||||
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
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)]
|
||||
public class DbReverseForeignObject : Attribute
|
||||
{
|
||||
public Type foreignObjectType;
|
||||
|
||||
public string _foreignKeyName;
|
||||
public DbForeignKey foreignKeyAttribute;
|
||||
|
||||
public FieldInfo parentField;
|
||||
public DbObject classAttribute;
|
||||
|
||||
/// <summary>
|
||||
/// Marks variable as reverse-foreign-object of an dbObject
|
||||
/// </summary>
|
||||
/// <param name="foreignKeyName">Fieldname of primaryKey associated with the reverseForeignObject (null if same as primary key) [Only works with 1 primaryKey]</param>
|
||||
public DbReverseForeignObject(string foreignKeyName = null)
|
||||
{
|
||||
this._foreignKeyName = foreignKeyName;
|
||||
}
|
||||
|
||||
public void Init(FieldInfo fi, DbObject classAttribute)
|
||||
{
|
||||
this.parentField = fi;
|
||||
this.classAttribute = classAttribute;
|
||||
this.foreignObjectType = fi.FieldType;
|
||||
|
||||
// Init foreign-object class
|
||||
DbObject foreignClassAttribute = ClassAction.Init(this.foreignObjectType);
|
||||
|
||||
if (classAttribute.primaryKeyAttributes.Count < 1) throw new InvalidOperationException($"'{classAttribute.parentClassType.Name}' does not have a primaryKey.");
|
||||
if (classAttribute.primaryKeyAttributes.Count > 1) throw new InvalidOperationException($"ReverseForeignObject does not support multiple primaryKeys.");
|
||||
// Get primaryKey name if none is set
|
||||
if (_foreignKeyName == null) _foreignKeyName = classAttribute.primaryKeyAttributes[0]._attributeName;
|
||||
|
||||
// Check if my primary-key is set in the foreign-class as foreignKey
|
||||
DbPrimaryKey primaryKey = classAttribute.primaryKeyAttributes[0];
|
||||
foreach (DbForeignKey foreignKey in foreignClassAttribute.foreignKeyAttributes)
|
||||
{
|
||||
if (primaryKey._attributeName.ToLower() == foreignKey._attributeName.ToLower()) // Name matches
|
||||
if (primaryKey.parentField.GetType() == foreignKey.parentField.GetType()) // Type matches
|
||||
{
|
||||
foreignKeyAttribute = foreignKey;
|
||||
}
|
||||
else
|
||||
// Same name, but wrong type
|
||||
throw new InvalidOperationException($"ForeignObject='{foreignClassAttribute.parentClassType.Name}' has invalid type foreignKey='{foreignKey.parentField.Name}' for object='{classAttribute.parentClassType.Name}' with primaryKey='{primaryKey.parentField.Name}'.");
|
||||
}
|
||||
// No match
|
||||
if (foreignKeyAttribute == null) throw new InvalidOperationException($"ForeignObject='{foreignClassAttribute.parentClassType.Name}' is missing foreignKey for object='{classAttribute.parentClassType.Name}' with primaryKey='{primaryKey.parentField.Name}'.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using eu.railduction.netcore.dll.Database_Attribute_System.Attributes;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
@ -126,7 +127,7 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
|
||||
}
|
||||
|
||||
// If no data was found matching this field
|
||||
if (!dataMatchFound) throw new InvalidOperationException($"Cannot create object with primaryKeyData. No data assigned to field '{primaryKeyAtt.parentField.Name}'");
|
||||
if (!dataMatchFound) throw new InvalidOperationException($"PrimaryKey='{primaryKeyAtt.parentField.Name}' is missing.");
|
||||
}
|
||||
|
||||
ResolveByPrimaryKey<T>(obj, queryExecutor);
|
||||
@ -276,22 +277,75 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
|
||||
// Read dbObject-attribute
|
||||
DbObject dbObject = ClassAction.Init(classType);
|
||||
|
||||
// Resolve foreignObjects
|
||||
|
||||
foreach (DbForeignObject foreignObjectAtt in dbObject.foreignObjectAttributes)
|
||||
{
|
||||
object foreignObject_value = foreignObjectAtt.parentField.GetValue(classObject);
|
||||
|
||||
// When its empty, get it
|
||||
// When its empty, get it & set it
|
||||
if(foreignObject_value == null)
|
||||
{
|
||||
foreignObject_value = GetByPrimaryKey<T>(classType, foreignObjectAtt.foreignKeyAttribute.parentField.GetValue(classObject), queryExecutor);
|
||||
foreignObjectAtt.parentField.SetValue(classObject, foreignObject_value);
|
||||
}
|
||||
|
||||
// Recursive resolving
|
||||
if (max_depth - 1 > 0)
|
||||
if (max_depth > 1)
|
||||
{
|
||||
// Go recursively into the next class
|
||||
ResolveForeignKeys(foreignObject_value, queryExecutor, max_depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve reverseForeignObjects
|
||||
foreach (DbReverseForeignObject reverseForeignObjectAtt in dbObject.reverseForeignObjectAttributes)
|
||||
{
|
||||
object reverseForeignObject_value = reverseForeignObjectAtt.parentField.GetValue(classObject);
|
||||
|
||||
// When its empty, get it & set it
|
||||
if (reverseForeignObject_value == null)
|
||||
{
|
||||
// Generate & set attribute-set
|
||||
Dictionary<string, object> attributes = new Dictionary<string, object>();
|
||||
attributes.Add(reverseForeignObjectAtt._foreignKeyName, dbObject.primaryKeyAttributes[0].parentField.GetValue(classObject));
|
||||
|
||||
List<object> values = GetListByAttribute<object>(reverseForeignObjectAtt.foreignKeyAttribute.classAttribute.parentClassType, attributes, queryExecutor);
|
||||
|
||||
if(values.Count == 0) throw new InvalidOperationException($"'{reverseForeignObjectAtt.parentField.Name}' could not been resolved. ReverseForeignObject returned '{values.Count}' values.");
|
||||
|
||||
// Check for type to determen 1:1 or 1:m
|
||||
Type reverseForeignObject_type = reverseForeignObjectAtt.parentField.GetType();
|
||||
if (reverseForeignObject_type is IList && reverseForeignObject_type.IsGenericType) // List, so 1:m
|
||||
{
|
||||
reverseForeignObject_value = values;
|
||||
}
|
||||
else // Not list, so 1:1
|
||||
{
|
||||
if (values.Count > 1) throw new InvalidOperationException($"'{reverseForeignObjectAtt.parentField.Name}' could not been resolved as ReverseForeignObject returned '{values.Count}' values. (Is it 1:1 instead of 1:m?)");
|
||||
reverseForeignObject_value = values[0];
|
||||
}
|
||||
reverseForeignObjectAtt.parentField.SetValue(classObject, reverseForeignObject_value);
|
||||
}
|
||||
|
||||
// Recursive resolving
|
||||
if (max_depth > 1)
|
||||
{
|
||||
if (reverseForeignObject_value is IList) // 1:m
|
||||
{
|
||||
// If we have a list of objects, we need to recursively go into each one
|
||||
foreach(object value in (IList)reverseForeignObject_value)
|
||||
{
|
||||
ResolveForeignKeys(value, queryExecutor, max_depth - 1);
|
||||
}
|
||||
}
|
||||
else // 1:1
|
||||
{
|
||||
// Go recursively into the next class
|
||||
ResolveForeignKeys(reverseForeignObject_value, queryExecutor, max_depth - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,6 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
|
||||
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)
|
||||
{
|
||||
@ -124,24 +119,24 @@ namespace eu.railduction.netcore.dll.Database_Attribute_System
|
||||
|
||||
public static string SqlSerialise(object obj)
|
||||
{
|
||||
if (obj == null) // Handle null
|
||||
if (obj == null || obj is DBNull) // Handle null
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
else if (obj.GetType() == typeof(string)) // Handle strings
|
||||
else if (obj is 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
|
||||
else if (obj is byte || obj is int || obj is float || obj is 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
|
||||
else if (obj is DateTime) // Handle DateTime
|
||||
{
|
||||
DateTime dateTime = (DateTime)obj;
|
||||
return "'" + SqlSerialise(dateTime) + "'"; // wrap in sql-brackets and convert to sql-datetime
|
||||
return "'" + dateTime.ToString("yyyy-MM-dd HH:mm:ss") + "'"; // wrap in sql-brackets and convert to sql-datetime
|
||||
}
|
||||
else if (obj.GetType() == typeof(Guid)) // Handle Guid
|
||||
else if (obj is Guid) // Handle Guid
|
||||
{
|
||||
string guid = ((Guid)obj).ToString(); // Get Guid as string
|
||||
return "'" + guid + "'"; // wrap in sql-brackets
|
||||
|
Loading…
x
Reference in New Issue
Block a user