/// -------------------------------------------------------------------------------- /// <summary> /// Extracts the fields to save to the database from the objItem.SaveFields function. /// The fields are then written to the database using either an SQL INSERT or UPDATE /// depending on whether the object has already been saved. If the collection has /// implemented IDatabaseObjects.KeyFieldName then objItem's key is also validated to /// ensure it is not null and unique within the collection. If objCollection has /// implemented IDatabaseObjects.Subset then objItem should exist within objCollection. /// If not, a duplicate key error may occur if the obItem's key is being used in /// another subset in the same table. If a record is being amended /// (IDatabaseObject.IsSaved returns true) then the function will "AND" the collection's /// IDatabaseObjects.Subset conditions and the objItem's IDatabaseObject.DistinctValue /// value to create the WHERE clause in the UPDATE statement. Therefore, the /// combination of the IDatabaseObjects.Subset and IDatabaseObject.DistinctValue /// conditions MUST identify only one record in the table. Otherwise multiple records /// will be updated with the same data. If data is only inserted and not amended /// (usually a rare occurance) then this requirement is unnecessary. /// </summary> /// /// <param name="objCollection"> /// The collection which contains or will contain the object to save. /// </param> /// /// <param name="objItem"> /// The object to save to the database. The values saved to the database are extracted from the /// SQLFieldValues object returned from IDatabaseObject.SaveFields. /// </param> /// /// <example> Saves a product object (Me) to the database. /// <code> /// Public Sub Save() /// /// objDatabase.ObjectSave(NorthwindDB.Products, Me) /// /// End Sub /// </code> /// </example> /// -------------------------------------------------------------------------------- /// public void ObjectSave(IDatabaseObjects objCollection, IDatabaseObject objItem) { SQL.SQLFieldValues objFieldValues; var objNewGUID = Guid.Empty; var autoAssignment = MergeDistinctFieldAutoAssignmentAndDistinctFieldAutoIncrements(objCollection); objFieldValues = objItem.SaveFields(); if (objFieldValues == null) throw new Exceptions.DatabaseObjectsException(objItem.GetType().Name + " IDatabaseObject.SaveFields not implemented"); //Add the distinct field value if it hasn't been added via the SaveFields sub if (!objFieldValues.Exists(objCollection.DistinctFieldName())) { if (autoAssignment == SQL.FieldValueAutoAssignmentType.None) objFieldValues.Add(objCollection.DistinctFieldName(), objItem.DistinctValue); else if (autoAssignment == SQL.FieldValueAutoAssignmentType.NewUniqueIdentifier) { //For a new object, with a GUID that should be automatically assigned //Create a new GUID for the distinct field so that it saved for the INSERT if (!objItem.IsSaved) { objNewGUID = System.Guid.NewGuid(); objFieldValues.Add(objCollection.DistinctFieldName(), objNewGUID); } } } #if !DEBUG ItemKeyEnsureValid(objCollection, objItem, objFieldValues); #endif using (ConnectionScope objConnection = new ConnectionScope(this)) { if (objItem.IsSaved) { var objUpdate = new SQL.SQLUpdate(); objUpdate.TableName = objCollection.TableName(); objUpdate.Fields.Add(objFieldValues); objUpdate.Where.Add(objCollection.DistinctFieldName(), SQL.ComparisonOperator.EqualTo, objItem.DistinctValue); var objSubset = objCollection.Subset(); if (objSubset != null && !objSubset.IsEmpty) { objUpdate.Where.Add(objSubset); } if (objConnection.ExecuteNonQuery(objUpdate) != 1) throw new Exceptions.RecordDoesNotExistException(objCollection, objItem); } else { var objInsert = new SQL.SQLInsert(); objInsert.TableName = objCollection.TableName(); objInsert.Fields = objFieldValues; objConnection.ExecuteNonQuery(objInsert); if (autoAssignment == SQL.FieldValueAutoAssignmentType.NewUniqueIdentifier) objItem.DistinctValue = objNewGUID; else if (autoAssignment == SQL.FieldValueAutoAssignmentType.AutoIncrement) objItem.DistinctValue = objConnection.ExecuteScalar(new SQL.SQLAutoIncrementValue()); object objRollbackDistinctValue = objItem.DistinctValue; objItem.IsSaved = true; if (Transaction.Current != null) { Transaction.Current.EnlistVolatile(new TransactionExecuteActionOnRollback(() => objItem.IsSaved = false), EnlistmentOptions.None); Transaction.Current.EnlistVolatile(new TransactionExecuteActionOnRollback(() => objItem.DistinctValue = objRollbackDistinctValue), EnlistmentOptions.None); } } } }
/// -------------------------------------------------------------------------------- /// <summary> /// Sets the field value for the database record associated with the object and /// collection. /// </summary> /// <param name="objCollection"> /// The collection that the object exists within. /// The function utilises the collection's subset and tablename to determine which /// table and record to modify. /// </param> /// <param name="objItem"> /// The object which represents the database record to be set. Specifically, /// the object's distinct field name is used to determine which record to modify. /// </param> /// <param name="strFieldName"> /// The name of the database field that is to be set. /// </param> /// <param name="objNewValue"> /// The new value that the database field it to be set to. /// If Nothing/null then the field is set to NULL. /// </param> /// <exception cref="Exceptions.ObjectDoesNotExistException">If the object has not already been saved</exception> /// -------------------------------------------------------------------------------- public void ObjectSetFieldValue(IDatabaseObjects objCollection, IDatabaseObject objItem, string strFieldName, object objNewValue) { if (!objItem.IsSaved) throw new Exceptions.ObjectDoesNotExistException(objItem); SQL.SQLUpdate objUpdate = new SQL.SQLUpdate(); objUpdate.TableName = objCollection.TableName(); objUpdate.Fields.Add(strFieldName, objNewValue); objUpdate.Where.Add(objCollection.DistinctFieldName(), SQL.ComparisonOperator.EqualTo, objItem.DistinctValue); var objSubset = objCollection.Subset(); if (objSubset != null && !objSubset.IsEmpty) objUpdate.Where.Add(objSubset); using (ConnectionScope objConnection = new ConnectionScope(this)) objConnection.ExecuteNonQuery(objUpdate); }