X Tutup
// created on 18/5/2002 at 01:25 // Npgsql.NpgsqlParameter.cs // // Author: // Francisco Jr. (fxjrlists@yahoo.com.br) // // Copyright (C) 2002 The Npgsql Development Team // npgsql-general@gborg.postgresql.org // http://gborg.postgresql.org/project/npgsql/projdisplay.php // // Permission to use, copy, modify, and distribute this software and its // documentation for any purpose, without fee, and without a written // agreement is hereby granted, provided that the above copyright notice // and this paragraph and the following two paragraphs appear in all copies. // // IN NO EVENT SHALL THE NPGSQL DEVELOPMENT TEAM BE LIABLE TO ANY PARTY // FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, // INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS // DOCUMENTATION, EVEN IF THE NPGSQL DEVELOPMENT TEAM HAS BEEN ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE. // // THE NPGSQL DEVELOPMENT TEAM SPECIFICALLY DISCLAIMS ANY WARRANTIES, // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS // ON AN "AS IS" BASIS, AND THE NPGSQL DEVELOPMENT TEAM HAS NO OBLIGATIONS // TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. using System; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Reflection; using System.Resources; using NpgsqlTypes; #if WITHDESIGN using Npgsql.Design; #endif namespace Npgsql { /// /// This class represents a parameter to a command that will be sent to server /// #if WITHDESIGN [TypeConverter(typeof(NpgsqlParameterConverter))] #endif public sealed class NpgsqlParameter : DbParameter, ICloneable { // Logging related values private static readonly String CLASSNAME = MethodBase.GetCurrentMethod().DeclaringType.Name; // Fields to implement IDbDataParameter interface. private byte precision = 0; private byte scale = 0; private Int32 size = 0; // Fields to implement IDataParameter //private NpgsqlDbType npgsqldb_type = NpgsqlDbType.Text; //private DbType db_type = DbType.String; private NpgsqlNativeTypeInfo type_info; private NpgsqlBackendTypeInfo backendTypeInfo; private ParameterDirection direction = ParameterDirection.Input; private Boolean is_nullable = false; private String m_Name = String.Empty; private String source_column = String.Empty; private DataRowVersion source_version = DataRowVersion.Current; private Object value = null; private Object npgsqlValue = null; private Boolean sourceColumnNullMapping; private NpgsqlParameterCollection collection = null; private static readonly ResourceManager resman = new ResourceManager(MethodBase.GetCurrentMethod().DeclaringType); private Boolean useCast = false; private static readonly NpgsqlNativeTypeInfo defaultTypeInfo = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); private bool bound = false; /// /// Initializes a new instance of the NpgsqlParameter class. /// public NpgsqlParameter() { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME); //type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); } /// /// Initializes a new instance of the NpgsqlParameter /// class with the parameter m_Name and a value of the new NpgsqlParameter. /// /// The m_Name of the parameter to map. /// An Object that is the value of the NpgsqlParameter. /// ///

When you specify an Object /// in the value parameter, the DbType is /// inferred from the .NET Framework type of the Object.

///

When using this constructor, you must be aware of a possible misuse of the constructor which takes a DbType parameter. /// This happens when calling this constructor passing an int 0 and the compiler thinks you are passing a value of DbType. /// Use Convert.ToInt32(value) for example to have compiler calling the correct constructor.

///
public NpgsqlParameter(String parameterName, object value) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, value); this.ParameterName = parameterName; this.Value = value; /*if ((this.value == null) || (this.value == DBNull.Value)) { // don't really know what to do - leave default and do further exploration // Default type for null values is String. this.value = DBNull.Value; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); } else if (!NpgsqlTypesHelper.TryGetNativeTypeInfo(value.GetType(), out type_info)) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType())); }*/ } /// /// The collection to which this parameter belongs, if any. /// public NpgsqlParameterCollection Collection { get { return collection; } internal set { collection = value; bound = false; } } /// /// Initializes a new instance of the NpgsqlParameter /// class with the parameter m_Name and the data type. /// /// The m_Name of the parameter to map. /// One of the DbType values. public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType) : this(parameterName, parameterType, 0, String.Empty) { } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the DbType values. public NpgsqlParameter(String parameterName, DbType parameterType) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, 0, String.Empty) { } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the NpgsqlDbType values. /// The length of the parameter. public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType, Int32 size) : this(parameterName, parameterType, size, String.Empty) { } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the DbType values. /// The length of the parameter. public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, String.Empty) { } /// /// Initializes a new instance of the NpgsqlParameter /// /// The m_Name of the parameter to map. /// One of the NpgsqlDbType values. /// The length of the parameter. /// The m_Name of the source column. public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType, Int32 size, String sourceColumn) { NpgsqlEventLog.LogMethodEnter(LogLevel.Debug, CLASSNAME, CLASSNAME, parameterName, parameterType, size, source_column); this.ParameterName = parameterName; NpgsqlDbType = parameterType; //Allow the setter to catch any exceptions. this.size = size; source_column = sourceColumn; } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the DbType values. /// The length of the parameter. /// The m_Name of the source column. public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size, String sourceColumn) : this(parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, sourceColumn) { } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the NpgsqlDbType values. /// The length of the parameter. /// The m_Name of the source column. /// One of the ParameterDirection values. /// true if the value of the field can be null, otherwise false. /// The total number of digits to the left and right of the decimal point to which /// Value is resolved. /// The total number of decimal places to which /// Value is resolved. /// One of the DataRowVersion values. /// An Object that is the value /// of the NpgsqlParameter. public NpgsqlParameter(String parameterName, NpgsqlDbType parameterType, Int32 size, String sourceColumn, ParameterDirection direction, bool isNullable, byte precision, byte scale, DataRowVersion sourceVersion, object value) { this.ParameterName = parameterName; this.Size = size; this.SourceColumn = sourceColumn; this.Direction = direction; this.IsNullable = isNullable; this.Precision = precision; this.Scale = scale; this.SourceVersion = sourceVersion; this.Value = value; if (this.value == null) { this.value = DBNull.Value; type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); } else { NpgsqlDbType = parameterType; //allow the setter to catch exceptions if necessary. } } /// /// Initializes a new instance of the NpgsqlParameter. /// /// The m_Name of the parameter to map. /// One of the DbType values. /// The length of the parameter. /// The m_Name of the source column. /// One of the ParameterDirection values. /// true if the value of the field can be null, otherwise false. /// The total number of digits to the left and right of the decimal point to which /// Value is resolved. /// The total number of decimal places to which /// Value is resolved. /// One of the DataRowVersion values. /// An Object that is the value /// of the NpgsqlParameter. public NpgsqlParameter(String parameterName, DbType parameterType, Int32 size, String sourceColumn, ParameterDirection direction, bool isNullable, byte precision, byte scale, DataRowVersion sourceVersion, object value) : this( parameterName, NpgsqlTypesHelper.GetNativeTypeInfo(parameterType).NpgsqlDbType, size, sourceColumn, direction, isNullable, precision, scale, sourceVersion, value) { } // Implementation of IDbDataParameter /// /// Gets or sets the maximum number of digits used to represent the /// Value property. /// /// The maximum number of digits used to represent the /// Value property. /// The default value is 0, which indicates that the data provider /// sets the precision for Value. [Category("Data"), DefaultValue((Byte)0)] public Byte Precision { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Precision"); return precision; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Precision", value); precision = value; bound = false; } } /// /// Whether to use an explicit cast when included in a query. /// public Boolean UseCast { get { // Prevents casts to be added for null values when they aren't needed. if (!useCast && (value == DBNull.Value || value == null)) return false; //return useCast; //&& (value != DBNull.Value); // This check for Datetime.minvalue and maxvalue is needed in order to // workaround a problem when comparing date values with infinity. // This is a known issue with postgresql and it is reported here: // http://archives.postgresql.org/pgsql-general/2008-10/msg00535.php // Josh's solution to add cast is documented here: // http://pgfoundry.org/forum/message.php?msg_id=1004118 return useCast || DateTime.MinValue.Equals(value) || DateTime.MaxValue.Equals(value) || !NpgsqlTypesHelper.DefinedType(Value); } } /// /// Gets or sets the number of decimal places to which /// Value is resolved. /// /// The number of decimal places to which /// Value is resolved. The default is 0. [Category("Data"), DefaultValue((Byte)0)] public Byte Scale { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Scale"); return scale; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Scale", value); scale = value; bound = false; } } /// /// Gets or sets the maximum size, in bytes, of the data within the column. /// /// The maximum size, in bytes, of the data within the column. /// The default value is inferred from the parameter value. [Category("Data"), DefaultValue(0)] public override Int32 Size { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "Size"); return size; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Size", value); size = value; bound = false; } } /// /// Gets or sets the DbType of the parameter. /// /// One of the DbType values. The default is String. [Category("Data"), RefreshProperties(RefreshProperties.All), DefaultValue(DbType.String)] public override DbType DbType { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "DbType"); if (type_info == null) return defaultTypeInfo.DbType; else return TypeInfo.DbType; } // [TODO] Validate data type. set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "DbType", value); useCast = value != DbType.Object; bound = false; if (!NpgsqlTypesHelper.TryGetNativeTypeInfo(value, out type_info)) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value)); } } } /// /// Gets or sets the DbType of the parameter. /// /// One of the DbType values. The default is String. [Category("Data"), RefreshProperties(RefreshProperties.All), DefaultValue(NpgsqlDbType.Text)] public NpgsqlDbType NpgsqlDbType { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "NpgsqlDbType"); if (type_info == null) return defaultTypeInfo.NpgsqlDbType; else return TypeInfo.NpgsqlDbType; } // [TODO] Validate data type. set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "NpgsqlDbType", value); useCast = true; bound = false; if (value == NpgsqlDbType.Array) { throw new ArgumentOutOfRangeException("value", resman.GetString("Exception_ParameterTypeIsOnlyArray")); } if (!NpgsqlTypesHelper.TryGetNativeTypeInfo(value, out type_info)) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value)); } } } internal NpgsqlNativeTypeInfo TypeInfo { get { if (type_info == null) { //type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); return defaultTypeInfo; } return type_info; } } /// /// Gets or sets a value indicating whether the parameter is input-only, /// output-only, bidirectional, or a stored procedure return value parameter. /// /// One of the ParameterDirection /// values. The default is Input. [Category("Data"), DefaultValue(ParameterDirection.Input)] public override ParameterDirection Direction { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "Direction"); return direction; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Direction", value); direction = value; } } /// /// Gets or sets a value indicating whether the parameter accepts null values. /// /// true if null values are accepted; otherwise, false. The default is false. #if WITHDESIGN [EditorBrowsable(EditorBrowsableState.Advanced), Browsable(false), DefaultValue(false), DesignOnly(true)] #endif public override Boolean IsNullable { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Debug, CLASSNAME, "IsNullable"); return is_nullable; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "IsNullable", value); is_nullable = value; } } /// /// Gets or sets the m_Name of the NpgsqlParameter. /// /// The m_Name of the NpgsqlParameter. /// The default is an empty string. [DefaultValue("")] public override String ParameterName { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "ParameterName"); return m_Name; } set { m_Name = value; if (value == null) { m_Name = String.Empty; } // no longer prefix with : so that the m_Name returned is the m_Name set m_Name = m_Name.Trim(); if (collection != null) { collection.InvalidateHashLookups(); bound = false; } NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "ParameterName", m_Name); } } /// /// The m_Name scrubbed of any optional marker /// internal string CleanName { get { string name = ParameterName; if (name[0] == ':' || name[0] == '@') { return name.Length > 1 ? name.Substring(1) : string.Empty; } return name; } } /// /// Gets or sets the m_Name of the source column that is mapped to the /// DataSet and used for loading or /// returning the Value. /// /// The m_Name of the source column that is mapped to the /// DataSet. The default is an empty string. [Category("Data"), DefaultValue("")] public override String SourceColumn { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "SourceColumn"); return source_column; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "SourceColumn", value); source_column = value; } } /// /// Gets or sets the DataRowVersion /// to use when loading Value. /// /// One of the DataRowVersion values. /// The default is Current. [Category("Data"), DefaultValue(DataRowVersion.Current)] public override DataRowVersion SourceVersion { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "SourceVersion"); return source_version; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "SourceVersion", value); source_version = value; } } /// /// Gets or sets the value of the parameter. /// /// An Object that is the value of the parameter. /// The default value is null. [TypeConverter(typeof(StringConverter)), Category("Data")] public override Object Value { get { return this.value; /* NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "Value"); //return value; NpgsqlBackendTypeInfo backendTypeInfo; if (NpgsqlTypesHelper.TryGetBackendTypeInfo(type_info.Name, out backendTypeInfo)) { return backendTypeInfo.ConvertToFrameworkType(NpgsqlValue); } throw new NotSupportedException(); */ } // [TODO] Check and validate data type. set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "Value", value); if ((value == null) || (value == DBNull.Value)) { // don't really know what to do - leave default and do further exploration // Default type for null values is String. this.value = value; this.npgsqlValue = value; bound = false; //if (type_info == null) //{ // type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); //} return; } if (type_info == null && !NpgsqlTypesHelper.TryGetNativeTypeInfo(value.GetType(), out type_info)) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType())); } if (backendTypeInfo == null && !NpgsqlTypesHelper.TryGetBackendTypeInfo(type_info.Name, out backendTypeInfo)) { throw new InvalidCastException(String.Format(resman.GetString("Exception_ImpossibleToCast"), value.GetType())); } else { this.npgsqlValue = backendTypeInfo.ConvertToProviderType(value); this.value = backendTypeInfo.ConvertToFrameworkType(npgsqlValue); bound = false; } } } /// /// Gets or sets the value of the parameter. /// /// An Object that is the value of the parameter. /// The default value is null. [TypeConverter(typeof(StringConverter)), Category("Data")] public Object NpgsqlValue { get { NpgsqlEventLog.LogPropertyGet(LogLevel.Normal, CLASSNAME, "NpgsqlValue"); return npgsqlValue; } set { NpgsqlEventLog.LogPropertySet(LogLevel.Normal, CLASSNAME, "NpgsqlValue", value); Value = value; bound = false; } } /// /// Reset DBType. /// public override void ResetDbType() { //type_info = NpgsqlTypesHelper.GetNativeTypeInfo(typeof(String)); type_info = null; this.Value = Value; bound = false; } /// /// Source column mapping. /// public override bool SourceColumnNullMapping { get { return sourceColumnNullMapping; } set { sourceColumnNullMapping = value; } } /// /// Creates a new NpgsqlParameter that /// is a copy of the current instance. /// /// A new NpgsqlParameter that is a copy of this instance. public NpgsqlParameter Clone() { // use fields instead of properties // to avoid auto-initializing something like type_info NpgsqlParameter clone = new NpgsqlParameter(); clone.precision = precision; clone.scale = scale; clone.size = size; clone.type_info = type_info; clone.direction = direction; clone.is_nullable = is_nullable; clone.m_Name = m_Name; clone.source_column = source_column; clone.source_version = source_version; clone.value = value; clone.sourceColumnNullMapping = sourceColumnNullMapping; return clone; } object ICloneable.Clone() { return Clone(); } internal bool Bound { get { return bound; } set { bound = value; } } } }
X Tutup