Beispiel #1
0
        /// <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);
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        /// <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);
        }
Beispiel #5
0
        /// <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);
            }
        }
Beispiel #6
0
        /// <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);
        }
Beispiel #7
0
        /// <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;
            }
        }
Beispiel #8
0
        /// <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());
        }
Beispiel #9
0
        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 });
        }
    }
Beispiel #10
0
        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);
                        }
                    }
                }
            }
        }