internal CUpdateQuery(CDataBase p_data_base, CObjectMap p_map, String p_table_name, SQL.CAssignmentList p_assignments, SQL.CWhereCondition p_update_condition) : base(p_data_base) { if (p_map == null) { throw new ArgumentNullException("You must specify an object map to use."); } if (p_table_name == null) { throw new ArgumentNullException("You must specify a table name to use."); } if (String.IsNullOrWhiteSpace(p_table_name)) { throw new ArgumentException("The specified table name may not consist only of whitespace."); } if (p_assignments == null) { throw new ArgumentNullException("You must specify assignments to use for the query."); } m_p_table_name = p_table_name; m_p_assignments = p_assignments; m_p_update_condition = p_update_condition; _m_p_map = p_map; }
/// <summary> /// Constructs a new select query with the given properties. /// </summary> /// <param name="p_data_base">The database the query is supposed to run against.</param> /// <param name="p_map">The object map the query is created for.</param> /// <param name="p_column_names">The columns that should be extracted by the query.</param> /// <param name="p_table_name">The name of the table this query should extract data from.</param> /// <param name="p_where_condition">The conditions that rows must satisfy to be matched in this query, or null if there should be no conditions.</param> internal CSelectQuery(CDataBase p_data_base, CObjectMap p_map, String p_table_name, String[] p_column_names, SQL.CWhereCondition p_where_condition) : base(p_data_base) { if (p_map == null) { throw new ArgumentNullException("You must specify a map to use."); } if (p_table_name == null) { throw new ArgumentNullException("You must specify a table name to use."); } if (String.IsNullOrWhiteSpace(p_table_name)) { throw new ArgumentException("The specified table name may not consist only of whitespace."); } if (p_column_names == null) { throw new ArgumentNullException("You must provide column names to use."); } m_p_columns = new ReadOnlyCollection <String>((IList <String>)p_column_names.Clone()); m_p_table_name = p_table_name; m_p_where_condition = p_where_condition; _m_p_map = p_map; }
/// <summary> /// Saves an Object into the database. Returns true if the Object was successfully saved, false otherwise. The objects status is captured immediately, but the queries are run asynchronously. /// </summary> /// <param name="p_obj">The Object to save.</param> /// <returns>A status object indicating the success/failure of the operation.</returns> public async Task <CDBWizardStatus> SaveAsync <T>(T p_obj) { CObjectMap p_object_map = CObjectMap.Get(p_obj.GetType()); if (p_object_map.m_p_begin_delete_call_back != null) { p_object_map.m_p_begin_delete_call_back(p_obj); } if (p_object_map.m_p_unique_keys.Count == 0) { throw new Exception("Cannot save Object without any identifying primary keys defined"); } CDBWizardStatus p_status = await p_object_map.SaveObjectAsync(this, p_obj); if (!p_status.IsError) { if (p_object_map.m_p_end_save_call_back != null) { p_object_map.m_p_end_save_call_back(p_obj); } return(p_status); } return(p_status); }
internal DbParameter[] GetWhereParams(DbCommand p_cmd, CObjectMap p_map) { List <DbParameter> p_params = new List <DbParameter>(); GetWhereParams(p_cmd, p_map, p_params, 0); return(p_params.ToArray()); }
private void GetWhereParams(DbCommand p_cmd, CObjectMap p_map, List <DbParameter> p_params, Int32 depth) { SStorePrimitiveOptions primitive_options; if (!p_map.m_p_primitives_map.TryGetValue(m_p_column_name, out primitive_options)) { throw new Exception("No values for column \"" + m_p_column_name + "\" loaded when trying to load parameters for type \"" + p_map.m_p_object_type.FullName + "\"."); } DbParameter p_param = p_cmd.CreateParameter(); p_param.ParameterName = "@whereparam" + depth.ToString(); p_param.Value = CHelper.MakePrimitiveType(CHelper.ToValueString(m_p_expected_value), primitive_options.m_primitive_type); p_param.DbType = primitive_options.m_primitive_type.ToDbType(); if (primitive_options.m_primitive_type.RequiresLength()) { if (m_p_expected_value is Array) { p_param.Size = ((Array)m_p_expected_value).Length; } else if (m_p_expected_value is String) { p_param.Size = ((String)m_p_expected_value).Length; } else { throw new InvalidOperationException("A db primitive type that requires a length is not an array."); } } p_params.Add(p_param); if (m_p_nested_condition != null) { m_p_nested_condition.GetWhereParams(p_cmd, p_map, p_params, depth + 1); } }
internal void SetObject(Object p_obj, String p_value_name, Dictionary <Object, CDataBaseObject> p_mapped_objects) { CDataBaseObject p_db_obj = null; if (p_obj != null) { if (!p_mapped_objects.TryGetValue(p_obj, out p_db_obj)) { p_db_obj = new CDataBaseObject(CObjectMap.Get(p_obj.GetType())); p_db_obj.MapFrom(p_obj, p_mapped_objects); if (p_db_obj.IsEmpty) { p_db_obj = null; } } } ESetObjectStatus status = SetDBObject(p_db_obj, p_value_name); switch (status) { case ESetObjectStatus.err_table_link_ambiguous: case ESetObjectStatus.err_table_not_linked: throw new Exception("Error while trying to set database Object from given value: " + status.ToString()); case ESetObjectStatus.success: break; } }
internal CDataBaseObject(CObjectMap p_map) { if (p_map == null) { throw new ArgumentNullException("You must provide an Object map."); } m_p_map = p_map; _m_p_values = new Dictionary <String, Object>(); }
/// <summary> /// Constructs a new database object and sets its internal values according to the given object. /// </summary> /// <param name="p_obj">The object that is used as base for this database object.</param> public CDataBaseObject(Object p_obj) { if (p_obj == null) { throw new ArgumentNullException("The object you provide must not be null."); } m_p_map = CObjectMap.Get(p_obj.GetType()); _m_p_values = new Dictionary <String, Object>(); MapFrom(p_obj, new Dictionary <Object, CDataBaseObject>()); }
private static void ProcessStoreAttributes(Type p_type) { // TODO: Think about inheritance more thoroughly... // Also GetCustomAttribute<T> may throw an ambiguity exception (nice library design, microsoft, vexing exceptions \o/) StoreAttributes.CTableAttribute p_store_table_attribute = p_type.GetCustomAttribute <StoreAttributes.CTableAttribute>(); if (p_store_table_attribute == null) { return; // table store attribute is the only attribute that matters when applied directly to a type. } CObjectMap p_object_map = CObjectMap.Get(p_type); // <- magic is in the ctor }
public void MapToClass <T>(T p_obj) where T : class { if (p_obj == null) { throw new ArgumentNullException("You must provide an Object."); } Action <CDataBaseObject> p_delegate = (Action <CDataBaseObject>)CObjectMap.Get(p_obj.GetType()).m_p_map_to_method.CreateDelegate(typeof(Action <CDataBaseObject>), p_obj); p_delegate(this); }
/// <summary> /// Deletes an object from the database. /// </summary> /// <param name="obj">The object that should be deleted from the database.</param> /// <returns>A status object indicating the success/failure of the operation</returns> public CDBWizardStatus Delete <T>(T obj) { CObjectMap p_object_map = CObjectMap.Get(obj.GetType()); if (p_object_map.m_p_begin_delete_call_back != null) { p_object_map.m_p_begin_delete_call_back(obj); } if (p_object_map.m_p_unique_keys.Count == 0) { throw new Exception("Cannot delete Object without any identifying primary keys defined"); } CDBWizardStatus p_status = p_object_map.DeleteObject(this, obj); return(p_status); }
public async Task <Tuple <CDBWizardStatus, CDataBaseObject> > LoadObjectAsync(Type p_object_type, Object p_primary_key_value) { CObjectMap p_object_map = CObjectMap.Get(p_object_type); CDataBaseObject p_result = new CDataBaseObject(p_object_map); CDBWizardStatus p_status = await p_object_map.LoadObjectAsync( this, new SQL.CWhereCondition(p_object_map.m_p_unique_keys[0].m_p_column_name, "=", p_primary_key_value.ToString()), p_result ); if (p_status.IsError) { p_result = null; } return(new Tuple <CDBWizardStatus, CDataBaseObject>(p_status, p_result)); }
/// <summary> /// Constructs a new Object link that connects the given source map with the given target map using the given foreign key. /// </summary> /// <param name="p_field">The field this link should bind.</param> /// <param name="p_foreign_key">The foreign key to link the given source and target map.</param> /// <param name="p_source_map">The source map that the link should refer to.</param> /// <param name="p_target_map">The target map that the link should refer to.</param> internal SObjectLink(EObjectLinkType type, FieldInfo p_field, Type p_target_type, CForeignKey p_foreign_key, CObjectMap p_source_map, CObjectMap p_target_map) : this() { if (p_target_type == null) { throw new ArgumentNullException("The specified target type may not be null."); } if (p_foreign_key == null) { throw new ArgumentNullException("The specified foreign key may not be null."); } if (p_source_map == null) { throw new ArgumentNullException("The specified source map may not be null."); } if (p_target_map == null) { throw new ArgumentNullException("The specified target map may not be null."); } m_type = type; m_p_field = p_field; // allowed to be null m_p_target_type = p_target_type; for (Int32 i = 0; i < p_foreign_key.m_p_source_columns.Count; ++i) { if (!p_source_map.m_p_primitives_map.ContainsKey(p_foreign_key.m_p_source_columns[i])) { throw new ArgumentException("The given foreign key contains the source column \"" + p_foreign_key.m_p_source_columns[i] + "\" which is not present in the source map."); } } for (Int32 i = 0; i < p_foreign_key.m_p_target_columns.Count; ++i) { if (!p_target_map.m_p_primitives_map.ContainsKey(p_foreign_key.m_p_target_columns[i])) { throw new ArgumentException("The given foreign key contains the target column \"" + p_foreign_key.m_p_target_columns[i] + "\" which is not present in the target map."); } } m_p_foreign_key = p_foreign_key; m_p_source_map = p_source_map; m_p_target_map = p_target_map; }
internal CInsertQuery(CDataBase p_data_base, Boolean update_on_duplicate_key, CObjectMap p_object_map, String[] p_column_names, params Object[][] p_values) : base(p_data_base) { if (p_object_map == null) { throw new ArgumentNullException("You must specify an object map to use."); } if (p_column_names == null) { throw new ArgumentNullException("You must specify columns names to use."); } if (p_values == null) { throw new ArgumentNullException("You must specify values to use."); } for (Int32 i = 0; i < p_values.Length; ++i) { if (p_values[i].Length != p_column_names.Length) { throw new ArgumentException("One set of values did not have exactly the same length as the column names provided."); } } m_p_keys = new ReadOnlyCollection <String>(p_object_map.m_p_unique_keys.Select(x => x.m_p_column_name).ToArray()); m_on_duplicate_key_update = update_on_duplicate_key; m_p_table_name = p_object_map.m_p_object_table; m_p_column_names = new ReadOnlyCollection <String>((IList <String>)p_column_names.Clone()); m_p_values = new ReadOnlyCollection <ReadOnlyCollection <Object> >((from p_value in p_values select new ReadOnlyCollection <Object>(p_value)).ToArray()); _m_p_map = p_object_map; _m_has_key = false; for (Int32 i = 0; i < m_p_keys.Count; ++i) { if (m_p_column_names.Contains(m_p_keys[i])) { _m_has_key = true; break; } } }
/// <summary> /// Returns an array of database parameters for this assignment. /// </summary> /// <param name="p_cmd">The command to create the parameters with.</param> /// <returns>An array containing the created database parameters.</returns> internal DbParameter[] GetAssignmentParameters(DbCommand p_cmd, CObjectMap p_map) { DbParameter[] p_params = new DbParameter[m_p_assignments.Count]; Int32 index = 0; foreach (KeyValuePair <String, String> assignment in m_p_assignments) { DbParameter p_param = p_cmd.CreateParameter(); p_param.ParameterName = "@assignparam" + index.ToString(); p_param.Value = CHelper.MakePrimitiveType(assignment.Value, p_map.m_p_primitives_map[assignment.Key].m_primitive_type); p_param.DbType = p_map.m_p_primitives_map[assignment.Key].m_primitive_type.ToDbType(); if (p_map.m_p_primitives_map[assignment.Key].m_primitive_type.RequiresLength()) { p_param.Size = assignment.Value.Length; } p_params[index] = p_param; ++index; } return(p_params); }
/// <summary> /// Loads an Object of the given type with the given criteria. The criteria must uniquely identify an Object, otherwise an exception is thrown. /// </summary> /// <typeparam name="T">The type of the Object to load.</typeparam> /// <param name="p_object_conditions">The criteria the loaded Object must match.</param> /// <returns>The loaded Object that matched the criteria. If no Object matches the criteria, default(T) is returned, if multiple objects matched, an error is thrown.</returns> public async Task <CDBWizardStatus> LoadClassAsync <T>(T p_obj, params KeyValuePair <String, Object>[] p_object_conditions) where T : class { CObjectMap p_object_map = CObjectMap.Get(p_obj.GetType()); if (p_object_map.m_p_begin_load_call_back != null) { p_object_map.m_p_begin_load_call_back(p_obj); } SQL.CWhereCondition[] p_conditions = new SQL.CWhereCondition[p_object_conditions.Length]; for (Int32 i = 0; i < p_object_conditions.Length; ++i) { p_conditions[i] = new SQL.CWhereCondition(p_object_conditions[i].Key, "=", p_object_conditions[i].Value); } CDataBaseObject p_db_obj = new CDataBaseObject(p_object_map); CDBWizardStatus p_status = await p_object_map.LoadObjectAsync( this, new SQL.CWhereCondition(p_conditions), p_db_obj ); if (!p_status.IsError) { try { p_db_obj.MapToClass(p_obj); if (p_object_map.m_p_end_load_call_back != null) { p_object_map.m_p_end_load_call_back(p_obj); } } catch (Exception p_except) { return(new CDBWizardStatus(EDBWizardStatusCode.err_exception_thrown, p_except)); } } return(p_status); }
/// <summary> /// Loads an Object of the given type with the given primary key. The criteria must uniquely identify an Object, otherwise an exception is thrown. /// </summary> /// <typeparam name="T">The type of the Object to load.</typeparam> /// <param name="p_primary_key_value">The criteria the loaded Object must match.</param> /// <returns>A status Object containing information about the success/failure of the operation.</returns> public async Task <CDBWizardStatus> LoadClassAsync <T>(T p_obj, Object p_primary_key_value) where T : class { CObjectMap p_object_map = CObjectMap.Get(p_obj.GetType()); if (p_object_map.m_p_begin_load_call_back != null) { p_object_map.m_p_begin_load_call_back(p_obj); } CDataBaseObject p_db_obj = new CDataBaseObject(p_object_map); if (p_object_map.m_p_unique_keys.Count == 0) { throw new Exception("The class \"" + typeof(T).FullName + "\" does not define a primary key."); } CDBWizardStatus p_status = await p_object_map.LoadObjectAsync( this, new SQL.CWhereCondition(p_object_map.m_p_unique_keys[0].m_p_column_name, "=", p_primary_key_value.ToString()), p_db_obj ); if (!p_status.IsError) { try { p_db_obj.MapToClass(p_obj); if (p_object_map.m_p_end_load_call_back != null) { p_object_map.m_p_end_load_call_back(p_obj); } } catch (Exception p_except) { return(new CDBWizardStatus(EDBWizardStatusCode.err_exception_thrown, p_except)); } } return(p_status); }
public Tuple <CDBWizardStatus, CDataBaseObject> LoadObject(Type p_object_type, Object p_primary_key_value) { CObjectMap p_object_map = CObjectMap.Get(p_object_type); CDataBaseObject p_result = new CDataBaseObject(p_object_map); if (p_object_map.m_p_unique_keys.Count == 0) { throw new Exception("The class \"" + p_object_type.FullName + "\" does not define a primary key."); } CDBWizardStatus p_status = p_object_map.LoadObject( this, new SQL.CWhereCondition(p_object_map.m_p_unique_keys[0].m_p_column_name, "=", p_primary_key_value.ToString()), p_result ); if (p_status.IsError) { p_result = null; } return(new Tuple <CDBWizardStatus, CDataBaseObject>(p_status, p_result)); }
/// <summary> /// Constructs a new delete query to delete columns matching the given condition from the given table. /// </summary> /// <param name="p_data_base">The database the query should be run against.</param> /// <param name="p_map">The object map this query is being created for.</param> /// <param name="p_table_name">The name of the table to delete rows from.</param> /// <param name="p_where_condition">The condition a row must satisfy to be deleted.</param> /// <param name="limit">The total number of rows to delete, or 0 if every matched row should be deleted.</param> internal CDeleteQuery(CDataBase p_data_base, CObjectMap p_map, String p_table_name, SQL.CWhereCondition p_where_condition, UInt64 limit) : base(p_data_base) { if (p_map == null) { throw new ArgumentNullException("The map may not be null."); } if (p_table_name == null) { throw new ArgumentNullException("You must specify a table name to use."); } if (String.IsNullOrWhiteSpace(p_table_name)) { throw new ArgumentException("The specified table name may not consist only of whitespace."); } m_p_table_name = p_table_name; m_p_where_condition = p_where_condition; m_limit = limit; _m_p_map = p_map; }
/// <summary> /// Constructs a new database connecting to a mysql server with the given String. This makes a blocking, synchronous connection attempt to test the connection String. /// </summary> /// <param name="p_connection_string">The connection String to use.</param> public CDataBase(String p_connection_string, EDriverType driver_type) { m_p_connection_string = p_connection_string; m_driver_type = driver_type; switch (driver_type) { case EDriverType.mysql: m_p_supported_primitives = new HashSet <EDBPrimitive>() { EDBPrimitive.@decimal, EDBPrimitive.int8, EDBPrimitive.int16, EDBPrimitive.int24, EDBPrimitive.int32, EDBPrimitive.int64, EDBPrimitive.uint8, EDBPrimitive.uint16, EDBPrimitive.uint24, EDBPrimitive.uint32, EDBPrimitive.uint64, EDBPrimitive.timestamp, EDBPrimitive.date, EDBPrimitive.time, EDBPrimitive.datetime, EDBPrimitive.year, EDBPrimitive.varbinary, EDBPrimitive.binary, EDBPrimitive.varchar, EDBPrimitive.@char, EDBPrimitive.text, EDBPrimitive.bit, EDBPrimitive.@float, EDBPrimitive.@double, EDBPrimitive.boolean }; using (MySqlConnection p_mysql_connection = new MySqlConnection()) { p_mysql_connection.ConnectionString = p_connection_string; try { p_mysql_connection.Open(); } catch (Exception) { throw; } } break; case EDriverType.mssql: m_p_supported_primitives = new HashSet <EDBPrimitive>() { EDBPrimitive.int64, EDBPrimitive.binary, EDBPrimitive.boolean, EDBPrimitive.@char, EDBPrimitive.datetime, EDBPrimitive.@decimal, EDBPrimitive.@double, EDBPrimitive.varbinary, EDBPrimitive.int32, EDBPrimitive.text, EDBPrimitive.varchar, EDBPrimitive.@float, EDBPrimitive.int16, EDBPrimitive.uint8, EDBPrimitive.varbinary, EDBPrimitive.date, EDBPrimitive.time, }; using (SqlConnection p_mssql_connection = new SqlConnection()) { p_mssql_connection.ConnectionString = p_connection_string; try { p_mssql_connection.Open(); } catch (Exception) { throw; } } break; default: throw new Exception("Invalid driver type specified."); } if (!CDataBase.s_allow_invalid_primitives) { CObjectMap.ThrowOnIncompatibility(this); } }
public void MapToStruct <T>(ref T p_obj) where T : struct { MapToStructDelegate <T> p_delegate = (MapToStructDelegate <T>)CObjectMap.Get(p_obj.GetType()).m_p_map_to_method.CreateDelegate(typeof(MapToStructDelegate <T>)); p_delegate(ref p_obj, this); }