/// <summary> /// Handles decoding an instance from a query result /// </summary> /// <param name="queryResult">The query result to decode</param> /// <returns>The item decoded from the query result</returns> private T __Decode(IQueryResult queryResult) { // Make the result T result = new T(); // Iterate over all properties for (int index = 0; index < myModelProperties.Length; index++) { // get a nice shorthand reference PropertyInfo pi = myModelProperties[index]; // Get the DataField attribute DataField field = pi.GetCustomAttribute <DataField>(); // Get the value from the query result object value = queryResult.Row[field.FieldName]; // If the value is DbNull, we need to explicitly cast the value to null if (value.GetType() == typeof(DBNull)) { value = null; } // Otherwise, we should have a value, we check to see if it is a nullable field else if (pi.PropertyType.IsGenericType && pi.PropertyType.Name.Remove(pi.PropertyType.Name.IndexOf('`')) == "Nullable") { // Get the type for the property from the nullable instance's generic types Type paramType = pi.PropertyType.GenericTypeArguments[0]; // If the value is a value type, and the given value is the same as the default value for that type, // we assume that the field should be null if (paramType.IsValueType && Activator.CreateInstance(paramType).Equals(value)) { value = null; } // If the value is null, simply set it to null if (value == null) { pi.SetValue(result, value); } // Otherwise else { // If it is a foriegn key to another table, use the value as a primary key to get the data from the table if (pi.GetCustomAttribute <ForeignKey>() != null) { pi.SetValue(result, DataAccess.FromPrimaryKeyWeak(pi.PropertyType, value)); } // Otherwise just cast it to the properties type and set the value else { pi.SetValue(result, Convert.ChangeType(value, pi.PropertyType.GenericTypeArguments[0])); } } } // Finally, for any other type else { // If it is a foriegn key to another table, use the value as a primary key to get the data from the table if (pi.GetCustomAttribute <ForeignKey>() != null) { pi.SetValue(result, DataAccess.FromPrimaryKeyWeak(pi.PropertyType, value)); } // Otherwise just cast it to the properties type and set the value else { pi.SetValue(result, Convert.ChangeType(value, pi.PropertyType)); } } } // return the decoded result return(result); }
/// <summary> /// Gets a collection of models from the database that match the fields set in the given model /// </summary> /// <param name="match">The model instance to match</param> /// <returns>A collection of models from the database</returns> public T[] GetMatches(T match) { // Iterate over dependancies for (int index = 0; index < myDependencies.Length; index++) { // Get the value from the property object pValue = myDependencies[index].GetValue(match); // IF the database does not contain something that matches, we know that we cannot have this instance if (pValue != null && !DataAccess.ExistsWeak(myDependencies[index].PropertyType, pValue)) { return(new T[0]); } } // We need to build two sides of the query, allocate strings string searchTerms = ""; string resultValues = ""; // We also need to store a list of values to insert as well as a list of query parameters List <object> insertParams = new List <object>(); List <QueryParam> queryParams = new List <QueryParam>(); // Iterate over each property for (int index = 0; index < myModelProperties.Length; index++) { // Get the value of the property object value = myModelProperties[index].GetValue(match); // Get the DataField attribute DataField dField = myModelProperties[index].GetCustomAttribute <DataField>(); // Check for a null value if (value == null) { // just ignore } // Next see if this is a foreign key else if (myModelProperties[index].GetCustomAttribute <ForeignKey>() != null) { // Use the DataAccess to get the primary key value for the instance object key = DataAccess.GetPrimaryKeyWeak(myModelProperties[index].PropertyType, value); // Append the the field name to the search searchTerms += string.Format("{0}=@{0} AND ", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(key); } // Otherwise it is a regular data field else if (myModelProperties[index].GetCustomAttribute <PrimaryKey>() == null) { // Append the the field name to the search searchTerms += string.Format("{0}=@{0} AND ", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(value); } resultValues += dField.FieldName + ","; } // Prep the final query string query = string.Format("select {1} from {0} where {2}", myTableName, resultValues.Trim(','), searchTerms.Remove(searchTerms.Length - 5, 4).Trim()); // Execute the query IQueryResult result = DataAccess.Execute(query, queryParams.ToArray(), insertParams.ToArray()); T[] results = new T[result.NumRows]; for (int index = 0; index < results.Length; index++) { results[index] = __Decode(result); result.MoveNext(); } // Return true if at least one row was effected return(results); }
/// <summary> /// Handles inserting a model instance into the database /// </summary> /// <param name="model">The model isntance to insert</param> /// <returns>True if the insert was successful, false if otherwise</returns> public bool Insert(T model) { // Iterate over dependancies for (int index = 0; index < myDependencies.Length; index++) { // Get the value from the property object pValue = myDependencies[index].GetValue(model); if (pValue == null && myDependencies[index].GetCustomAttribute <Nullable>() == null) { throw new InvalidOperationException("Cannot insert with a missing dependancy"); } // IF the database does not contain something that matches, add one if (!DataAccess.ExistsWeak(myDependencies[index].PropertyType, pValue)) { DataAccess.InsertWeak(myDependencies[index].PropertyType, pValue); } myDependencies[index].SetValue(model, DataAccess.MatchWeak(myDependencies[index].PropertyType, pValue)[0]); } // We need to build two sides of the query, allocate strings string insertLeft, insertRight; insertLeft = insertRight = ""; // We also need to store a list of values to insert as well as a list of query parameters List <object> insertParams = new List <object>(); List <QueryParam> queryParams = new List <QueryParam>(); // Iterate over each property for (int index = 0; index < myModelProperties.Length; index++) { // Get the value of the property object value = myModelProperties[index].GetValue(model); // Get the DataField attribute DataField dField = myModelProperties[index].GetCustomAttribute <DataField>(); // We only include in insert if auto-generaed is false if (myModelProperties[index].GetCustomAttribute <AutoGenerated>() == null) { // Check for a null value if (value == null) { // If we do not allow null, throw an exception, otherwise ignore if (myModelProperties[index].GetCustomAttribute <Nullable>() == null) { throw new InvalidOperationException("Cannot insert with non-nullable field not set: " + myModelProperties[index].Name); } } // Next see if this is a foreign key else if (myModelProperties[index].GetCustomAttribute <ForeignKey>() != null) { // Use the DataAccess to get the primary key value for the instance object key = DataAccess.GetPrimaryKeyWeak(myModelProperties[index].PropertyType, value); // Append the field name to the left string insertLeft += dField.FieldName + ","; // Append the field name as a parameter to the right string insertRight += string.Format("@{0},", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(key); } // Otherwise it is a regular data field else { // Append the field name to the left string insertLeft += dField.FieldName + ","; // Append the field name as a parameter to the right string insertRight += string.Format("@{0},", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(value); } } } // Prep the final query string query = string.Format("insert into {0} ({1}) VALUES ({2})", myTableName, insertLeft.Trim(','), insertRight.Trim(',')); // Execute the query int results = DataAccess.ExecuteStatement(query, queryParams.ToArray(), insertParams.ToArray()); // Return true if at least one row was effected return(results > 0); }
/// <summary> /// Handles updating a model in the database /// </summary> /// <param name="value">The value of the model to update</param> /// <param name="updateNullValues">True if null values should be assigned to null in the database, false to keep existing</param> /// <param name="updateChildren">True if referenced items should be updated, false if otherwise</param> /// <returns>The number of rows to be modified. In most cases this should be 1</returns> public int Update(T value, bool updateNullValues = true, bool updateChildren = true) { // Iterate over dependancies if (updateChildren) { for (int index = 0; index < myDependencies.Length; index++) { // Get the value from the property object pValue = myDependencies[index].GetValue(value); // If the value is null and the field is not nullable if (pValue == null && myDependencies[index].GetCustomAttribute <Nullable>() == null) { // if we are trying to update the nullable fields, throw an exception if (updateNullValues) { throw new InvalidOperationException("Cannot insert with a missing dependancy"); } } else { // IF the database does not contain something that matches, add one if (!DataAccess.ExistsWeak(myDependencies[index].PropertyType, pValue)) { DataAccess.InsertWeak(myDependencies[index].PropertyType, pValue); myDependencies[index].SetValue(value, DataAccess.MatchWeak(myDependencies[index].PropertyType, pValue)[0]); } else if (updateChildren) { DataAccess.UpdateWeak(myDependencies[index].PropertyType, pValue); } } } } // We need to build two sides of the query, allocate strings string updateValues, updateSearch; updateValues = updateSearch = ""; // We also need to store a list of values to insert as well as a list of query parameters List <object> insertParams = new List <object>(); List <QueryParam> queryParams = new List <QueryParam>(); // Iterate over each property for (int index = 0; index < myModelProperties.Length; index++) { // Get the value of the property object pValue = myModelProperties[index].GetValue(value); // Get the DataField attribute DataField dField = myModelProperties[index].GetCustomAttribute <DataField>(); if (myModelProperties[index].GetCustomAttribute <PrimaryKey>() != null) { if (myModelProperties[index].GetCustomAttribute <ForeignKey>() != null) { // Use the DataAccess to get the primary key value for the instance pValue = DataAccess.GetPrimaryKeyWeak(myModelProperties[index].PropertyType, pValue); } if (pValue == null) { throw new ArgumentException("Cannot update without primary key set. Has this record been retreived from the DB?"); } // Append the field name as a parameter to the right string updateSearch += string.Format("{0}=@{0} AND ", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(pValue); } // We only include in insert if auto-generaed is false else if (myModelProperties[index].GetCustomAttribute <AutoGenerated>() == null) { // Check for a null value if (pValue == null) { if (updateNullValues) { // If we do not allow null, throw an exception, otherwise ignore if (myModelProperties[index].GetCustomAttribute <Nullable>() == null) { throw new InvalidOperationException("Cannot insert with non-nullable field not set: " + myModelProperties[index].Name); } else { updateValues += string.Format("{0}=null,", dField.FieldName); } } } // Next see if this is a foreign key else if (myModelProperties[index].GetCustomAttribute <ForeignKey>() != null) { // Use the DataAccess to get the primary key value for the instance object key = DataAccess.GetPrimaryKeyWeak(myModelProperties[index].PropertyType, pValue); // Append the field name to the left string updateValues += string.Format("{0}=@{0},", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(key); } // Otherwise it is a regular data field else { // Append the field name to the left string updateValues += string.Format("{0}=@{0},", dField.FieldName); // Make and insert the query parameter queryParams.Add(new QueryParam(dField.FieldName, dField.FieldType)); // Add that key value we got insertParams.Add(pValue); } } } // Prep the final query string query = string.Format("update {0} set {1} where {2}", myTableName, updateValues.Trim(','), updateSearch.Remove(updateSearch.Length - 5, 4).Trim()); // Execute the query int results = DataAccess.ExecuteStatement(query, queryParams.ToArray(), insertParams.ToArray()); // Return true if at least one row was effected return(results); }