/// <summary> /// Appends the field to the data map /// </summary> /// <param name="field"></param> private void AppendField(IDataMapField field) { if (_dataFieldsDict.ContainsKey(field.FieldName)) { throw new Exception(string.Format("Field '{0}' already exists in _dataFieldsDict", field.FieldName)); } _dataFieldsDict.Add(field.FieldName, field); if (_propsToFields.ContainsKey(field.Property)) { throw new Exception(string.Format("Property '{0}' already exists in _propsToFields", field.Property)); } _propsToFields.Add(field.Property, field); if (field.IsKeyField) { if (_keyFields.Contains(field)) { throw new Exception(string.Format("Field '{0}' already exists in _keyFields", field)); } _keyFields.Add(field); } if (field.AccessType != AccessType.WriteOnly) { if (_readableFieldsDict.ContainsKey(field.FieldName)) { throw new Exception(string.Format("Field '{0}' already exists in _readableFieldsDict", field.FieldName)); } _readableFieldsDict.Add(field.FieldName, field); } }
public DbCommand GetUpdateRowsCommand(IDictionary <string, object> setClause, string filterText) { DbCommand command = GetTextCommand(""); var setString = new StringBuilder(); var setParmList = new List <DbParameter>(); foreach (KeyValuePair <string, object> pair in setClause) { PropertyInfo pi = _dataObjectType.GetProperty(pair.Key); if (pi == null) { throw new ArgumentException(string.Format("Cannot match property '{0}'", pair.Key)); } IDataMapField field = _dataMap.GetFieldForProperty(pi); if (field == null) { throw new ArgumentException(string.Format("Cannot match DataMap field '{0}'", pair.Key)); } string sFieldDescr = _dialect.FormatFieldName(field.FieldName, (field.UseQuotedIdentifier ?? UseQuotedIdentifier)); if (setString.Length > 0) { setString.Append(", "); } DbParameter setParm = CreateSetParam(command, field); setString.Append(sFieldDescr); setString.Append(" = "); setString.Append(setParm.ParameterName); if (pi.PropertyType == typeof(string)) { SetStringParamValue(field, setParm, pair.Value, false); } else { setParm.Value = (pair.Value ?? DBNull.Value); } setParmList.Add(setParm); } if (setParmList.Count == 0) { return(null); } command.CommandText = String.Format("UPDATE {0} SET {1} WHERE {2};", SaveToTable, setString, filterText); command.Parameters.AddRange(setParmList.ToArray()); if (_dialect.SupportsChangeContext && ChangeTrackingContext != null) { _dialect.ApplyChangeTrackingContext(command, ChangeTrackingContext); } return(command); }
private static DataMap GenerateMapInternal(Type type, string tableName, IEnumerable <string> keyFields, int schemaVersion) { if (schemaVersion == 0) { schemaVersion = int.MaxValue; } var map = new DataMap(type); // get or create data item IDataMapItem theDataItem = DataItemAttribute.GetFromTypeOrMember(type); if (theDataItem != null) { if (!string.IsNullOrEmpty(tableName)) { theDataItem.TableName = tableName; } } else { theDataItem = new DataMapItem(tableName, true); } // assign to data map map.DataItem = theDataItem; // create fields from properties foreach (var pi in type.GetProperties()) { IDataMapField field = DataFieldAttribute.GetFromProperty(pi); if ((field == null) && theDataItem.ImplicitFieldDefinition) { field = new DataMapField(pi, pi.Name, DataManager.GetDbType(pi.PropertyType), true); if (keyFields.Contains(field.FieldName, StringComparer.OrdinalIgnoreCase)) { field.IsKeyField = true; } if ((pi.PropertyType == typeof(byte[])) && field.FieldName.Equals("rowVersion", StringComparison.OrdinalIgnoreCase)) { field.IsRowVersion = true; } } if ((field != null) && (field.SchemaVersion <= schemaVersion)) { map.AppendField(field); } } return(map); }
/// <summary> /// Adds the field. /// </summary> /// <param name="field">The field.</param> public void AddField(IDataMapField field) { if (field == null) { throw new ArgumentNullException("field"); } if (field.Property == null) { throw new ArgumentException("field.Property cannot be null"); } AppendField(field); }
/// <summary> /// Removes the field from the data map. /// </summary> /// <param name="fieldName">Name of the field.</param> public void RemoveField(string fieldName) { IDataMapField field = this[fieldName]; if (field == null) { return; } _dataFieldsDict.Remove(field.FieldName); _propsToFields.Remove(field.Property); if (field.IsKeyField) { _keyFields.Remove(field); } if (field.AccessType != AccessType.WriteOnly) { _readableFieldsDict.Remove(field.FieldName); } }
/// <summary> /// Creates the set param. /// </summary> /// <param name="command">The command.</param> /// <param name="field">The field.</param> /// <returns></returns> private DbParameter CreateSetParam(DbCommand command, IDataMapField field) { DbParameter param = command.CreateParameter(); param.ParameterName = _dialect.FormatParameterName(field.FieldName, command.CommandType); param.SourceColumn = field.FieldName; if ((param is SqlParameter) && (field.DataType == DbType.Time)) // hack M$ issue { ((SqlParameter)param).SqlDbType = SqlDbType.Time; } else { param.DbType = field.DataType; } if (field.Length >= 0) { param.Size = field.Length; } return(param); }
/// <summary> /// Sets a string parameter value. /// </summary> /// <param name="field">The field.</param> /// <param name="parm">The parm.</param> /// <param name="value">The value.</param> /// <param name="inserting">if set to <c>true</c> [inserting].</param> private void SetStringParamValue(IDataMapField field, IDataParameter parm, object value, bool inserting) { if (value == null) { parm.Value = (inserting) ? _nullStringDefault : DBNull.Value; return; } string sValue = value.ToString(); if ((field.Length > 0) && (sValue.Length > field.Length)) { if (!field.TrimToFit) { throw new ArgumentOutOfRangeException(string.Format("Data Field `{0}` has a maximum length of {1} and was supplied a value with a length of {2}.", field.FieldName, field.Length, sValue.Length)); } parm.Value = sValue.Substring(0, field.Length); } else { parm.Value = sValue; } }
/// <summary> /// Gets the conflicts. /// </summary> /// <param name="obj">The obj.</param> /// <returns>A <see cref="Zonkey.Conflict"/> array.</returns> public Conflict[] GetConflicts(T obj) { ISavable objSV = obj as ISavable; if (objSV == null) { throw new ArgumentException("GetConflicts() is only supported on classes that implement Zonkey.ObjectModel.ISavable", "obj"); } FieldValuesDictionary dbValues; DbCommand command = CommandBuilder.GetRequeryCommand(objSV); using (DbDataReader reader = ExecuteReaderInternal(command, CommandBehavior.SingleRow)) { if (reader.Read()) { dbValues = new FieldValuesDictionary(reader); } else { throw new DataException("DataReader returned could not read a record to sync with."); } } List <Conflict> conflicts = new List <Conflict>(); foreach (KeyValuePair <string, object> original in objSV.OriginalValues) { PropertyInfo pi = _objectType.GetProperty(original.Key); if (pi == null) { continue; } IDataMapField field = DataMap.GetFieldForProperty(pi); if ((field == null) || (field.AccessType == AccessType.ReadOnly)) { continue; } bool valueMatch = false; object oDbValue; if (dbValues.TryGetValue(field.FieldName, out oDbValue)) { if (IsNullOrDbNull(original.Value) || IsNullOrDbNull(oDbValue)) { valueMatch = (IsNullOrDbNull(original.Value) && IsNullOrDbNull(oDbValue)); } else { Type propType = original.Value.GetType(); if (propType.IsGenericType) { // special case to handle nullable types Type baseType = Nullable.GetUnderlyingType(propType); if (baseType != null) { propType = baseType; } } if (propType.IsEnum) { propType = Enum.GetUnderlyingType(propType); } if (!propType.IsAssignableFrom(oDbValue.GetType())) { if ((propType == typeof(Guid)) && (oDbValue is string)) { if (!string.IsNullOrEmpty(oDbValue.ToString())) { valueMatch = original.Value.Equals(new Guid(oDbValue.ToString())); } } else { valueMatch = original.Value.Equals(Convert.ChangeType(oDbValue, propType)); } } else { valueMatch = original.Value.Equals(oDbValue); } } } else { throw new DataException(string.Format("Missing field '{0}' from db sync query", field.FieldName)); } if (!valueMatch) { conflicts.Add(new Conflict(field.Property.Name, original.Value, oDbValue, field.Property.GetValue(objSV, null))); } } return(conflicts.ToArray()); }
public DbCommand[] GetUpdate2Commands(ISavable obj, UpdateCriteria criteria, bool doSelectBack) { if (obj == null) { throw new ArgumentNullException("obj"); } if (obj.GetType() != _dataObjectType) { throw new ArgumentException("Type of 'obj' does not match type from constructor."); } if (criteria == UpdateCriteria.AllFields) { throw new ArgumentException("UpdateCriteria.AllFields is not supported by Update2 methods."); } // set update criteria - default is changed fields if (criteria == UpdateCriteria.Default) { criteria = (_dataMap.DataItem.UpdateCriteria == UpdateCriteria.Default) ? UpdateCriteria.ChangedFields : _dataMap.DataItem.UpdateCriteria; } if (criteria == UpdateCriteria.KeyAndVersion) { criteria = UpdateCriteria.ChangedFields; } // check for keys if (_dataMap.KeyFields.Count == 0) { throw new InvalidOperationException(String.Format("Class '{0}' does not contain any properties with DataFieldAttributes or none are marked with IsKeyField.", _dataObjectType.FullName)); } // init commands DbCommand updateCommand = GetTextCommand(""); DbCommand selectCommand = (doSelectBack) ? GetTextCommand("") : null; // create string builders and param lists var setString = new StringBuilder(); var setParmList = new List <DbParameter>(); var whereString = new StringBuilder(); var whereParmList = new List <DbParameter>(); foreach (KeyValuePair <string, object> changedField in obj.OriginalValues) { PropertyInfo pi = _dataObjectType.GetProperty(changedField.Key); if (pi == null) { continue; } IDataMapField field = _dataMap.GetFieldForProperty(pi); if ((field == null) || (field.AccessType == AccessType.ReadOnly)) { continue; } if ((field.IsAutoIncrement) || (field.IsRowVersion)) { continue; } string sFieldDescr = _dialect.FormatFieldName(field.FieldName, (field.UseQuotedIdentifier ?? UseQuotedIdentifier)); if (field.IsKeyField || (criteria >= UpdateCriteria.ChangedFields) || (field.IsRowVersion && (criteria == UpdateCriteria.KeyAndVersion)) ) { // A primary key or row version if (whereString.Length > 0) { whereString.Append(" AND "); } object oParmValue = (changedField.Value ?? DBNull.Value); // add to command if (Convert.IsDBNull(oParmValue)) { whereString.AppendFormat("{0} IS NULL", sFieldDescr); } else if (!field.IsComparable) { whereString.AppendFormat("{0} IS NOT NULL", sFieldDescr); } else { DbParameter whereParam = CreateWhereParam(updateCommand, field); whereString.Append(sFieldDescr); whereString.Append(" = "); whereString.Append(whereParam.ParameterName); whereParam.Value = oParmValue; whereParmList.Add(whereParam); } } if (setString.Length > 0) { setString.Append(", "); } DbParameter setParm = CreateSetParam(updateCommand, field); setString.Append(sFieldDescr); setString.Append(" = "); setString.Append(setParm.ParameterName); if (pi.PropertyType == typeof(string)) { SetStringParamValue(field, setParm, pi.GetValue(obj, null), false); } else { setParm.Value = (pi.GetValue(obj, null) ?? DBNull.Value); } setParmList.Add(setParm); } if (setParmList.Count == 0) { return(null); } var keyString = new StringBuilder(); var keyParmList = new List <DbParameter>(); foreach (IDataMapField field in _dataMap.KeyFields) { PropertyInfo pi = field.Property; if (pi == null) { continue; } string sFieldDescr = _dialect.FormatFieldName(field.FieldName, (field.UseQuotedIdentifier ?? UseQuotedIdentifier)); if (doSelectBack) { DbParameter keyParam = CreateWhereParam(selectCommand, field); if (keyString.Length > 0) { keyString.Append(" AND "); } keyString.Append(sFieldDescr); keyString.Append(" = "); keyString.Append(keyParam.ParameterName); keyParam.Value = pi.GetValue(obj, null); keyParmList.Add(keyParam); } // A primary key or row version if (whereString.Length > 0) { whereString.Append(" AND "); } // get value for parameter object oParmValue; if (obj.OriginalValues.ContainsKey(pi.Name)) { oParmValue = (obj.OriginalValues[pi.Name] ?? DBNull.Value); } else { oParmValue = (pi.GetValue(obj, null) ?? DBNull.Value); } // add to command if (Convert.IsDBNull(oParmValue)) { whereString.AppendFormat("{0} IS NULL", sFieldDescr); } else { DbParameter whereParam = CreateWhereParam(updateCommand, field); whereString.Append(sFieldDescr); whereString.Append(" = "); whereString.Append(whereParam.ParameterName); whereParam.Value = oParmValue; whereParmList.Add(whereParam); } } // setup update command updateCommand.CommandText = String.Format("UPDATE {0} SET {1} WHERE {2};", SaveToTable, setString, whereString); updateCommand.Parameters.AddRange(setParmList.ToArray()); updateCommand.Parameters.AddRange(whereParmList.ToArray()); if (_dialect.SupportsChangeContext && ChangeTrackingContext != null) { _dialect.ApplyChangeTrackingContext(updateCommand, ChangeTrackingContext); } if (!doSelectBack) // if no select-back return now { return new[] { updateCommand, null } } ; // setup select command and return both selectCommand.CommandText = String.Format("SELECT {0} FROM {1} WHERE {2};", ColumnsString, TableName, keyString); selectCommand.Parameters.AddRange(keyParmList.ToArray()); return(new[] { updateCommand, selectCommand }); } }
private void PopulateSingleObject(T obj, IDataRecord record, bool skipDbNull) { lock (obj) { for (int i = 0; i < record.FieldCount; i++) { IDataMapField field = DataMap.GetReadableField(record.GetName(i)); if (field == null) { continue; } PropertyInfo pi = field.Property; if (pi == null) { continue; } Type propType = pi.PropertyType; if (propType.IsEnum) { propType = Enum.GetUnderlyingType(propType); } if (record.IsDBNull(i)) { if (skipDbNull) { continue; } if ((!propType.IsValueType) || (Nullable.GetUnderlyingType(propType) != null)) { pi.SetValue(obj, null, null); } } else { object oValue = record.GetValue(i); Type dbFieldType = record.GetFieldType(i); try { if (!propType.IsAssignableFrom(dbFieldType)) { if ((propType == typeof(Guid)) && (oValue is string)) { pi.SetValue(obj, new Guid(oValue.ToString()), null); } else if (dbFieldType.Name.EndsWith("SqlHierarchyId")) // if the column is a HierarchyID type, then just treat it as a string (SQL server can implicitly convert between the two) { pi.SetValue(obj, oValue.ToString(), null); } else { pi.SetValue(obj, Convert.ChangeType(oValue, propType), null); } } else if ((oValue is DateTime) && (field.DateTimeKind != DateTimeKind.Unspecified)) { // special date/time handling for UTC and Local times var dtValue = new DateTime(((DateTime)oValue).Ticks, field.DateTimeKind); pi.SetValue(obj, dtValue, null); } else { pi.SetValue(obj, oValue, null); } } catch (Exception ex) { throw new PropertyReadException(pi, oValue, ex); } } } } }