validar fecha enviar desde c# .net sql-server nullable

validar - enviar fecha null desde c#



SqlParameter con valor Nullable da error mientras ExecuteNonQuery? (2)

Los tipos no son compatibles. Intenta algo como esto:

dbParam_au_id.Value = (object)birthday ?? DBNull.Value;

Tengo una consulta de SQL que tiene un parámetro que puede ser nulo en la base de datos (Servidor SQL). El método de actualización funciona bien hasta que el usuario pone un espacio en blanco en el campo, esto produce un valor nulo para el objeto DataTime (este objeto es anulable). El problema es cuando dbCommand.ExecuteNonQuery(); .

Así es como construyo el parámetro para este campo:

IDataParameter dbParam_au_id = new SqlParameter(); dbParam_au_id.ParameterName = "@birthday"; dbParam_au_id.Value = birthday; dbParam_au_id.DbType = DbType.DateTime; dbCommand.Parameters.Add(dbParam_au_id);

He intentado convertir el valor nulo de cumpleaños a DBNull.Value así:

IDataParameter dbParam_au_id = new SqlParameter(); dbParam_au_id.ParameterName = "@birthday"; dbParam_au_id.Value = birthday??DBNull.Value; dbParam_au_id.DbType = DbType.DateTime; dbCommand.Parameters.Add(dbParam_au_id);

Pero este código no compilará y me sale un error:

Error 1 Operador ''??'' no se puede aplicar a los operandos de tipo ''System.DateTime?'' y ''System.DBNull''

¿Alguna idea?


Si la clase SqlParameter se escribió correctamente la primera vez ... un valor nulo de C # se manejaría como DBNull.Value. Eso sería intuitivo, por lo que, por supuesto, establecer un valor de parámetro SqlParameter en nulo es funcionalmente equivalente a eliminarlo de la colección SqlParameterCollection.

Para corregir este ridículo error de diseño de la API, cree su propio método AddParameter (con sobrecargas), que toma una SqlParameterCollection, una Cadena (nombre del parámetro) y un Objeto (valor del parámetro).

#region Add by Name/Value. /// <summary> /// Adds an input parameter with a name and value. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="value">The value of the parameter to add.</param> private static void AddParameter( SqlParameterCollection parameters, string name, object value ) { parameters.Add( new SqlParameter( name, value ?? DBNull.Value ) ); } /// <summary> /// Adds a parameter with a name and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> /// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> private static void AddParameter( SqlParameterCollection parameters, string name, object value, ParameterDirection direction ) { SqlParameter parameter = new SqlParameter( name, value ?? DBNull.Value ); parameter.Direction = direction; parameters.Add( parameter ); } #endregion #region Add by Name, Type, and Value. /// <summary> /// Adds an input parameter with a name, type, and value. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="type">Specifies the SqlDbType of the parameter.</param> /// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> private static void AddParameter( SqlParameterCollection parameters, string name, SqlDbType type, object value ) { AddParameter( parameters, name, type, 0, value ?? DBNull.Value, ParameterDirection.Input ); } /// <summary> /// Adds a parameter with a name, type, and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="type">Specifies the SqlDbType of the parameter.</param> /// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> /// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> private static void AddParameter( SqlParameterCollection parameters, string name, SqlDbType type, object value, ParameterDirection direction ) { AddParameter( parameters, name, type, 0, value ?? DBNull.Value, direction ); } #endregion #region Add by Name, Type, Size, and Value. /// <summary> /// Adds an input parameter with a name, type, size, and value. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="type">Specifies the SqlDbType of the parameter.</param> /// <param name="size">Specifies the size of the parameter for parameter types of variable size. Set to zero to use the default size.</param> /// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> private static void AddParameter( SqlParameterCollection parameters, string name, SqlDbType type, int size, object value ) { AddParameter( parameters, name, type, size, value ?? DBNull.Value, ParameterDirection.Input ); } /// <summary> /// Adds a parameter with a name, type, size, and value. You specify the input/output direction. Automatically handles conversion of null object values to DBNull.Value. /// </summary> /// <param name="parameters">SqlParameterCollection from an SqlCommand instance.</param> /// <param name="name">The name of the parameter to add.</param> /// <param name="type">Specifies the SqlDbType of the parameter.</param> /// <param name="size">Specifies the size of the parameter for parameter types of variable size. Set to zero to use the default size.</param> /// <param name="value">The value of the parameter to add. If null, this is automatically converted to DBNull.Value.</param> /// <param name="direction">The ParameterDirection of the parameter to add (input, output, input/output, or return value).</param> private static void AddParameter( SqlParameterCollection parameters, string name, SqlDbType type, int size, object value, ParameterDirection direction ) { SqlParameter parameter; if (size < 1) parameter = new SqlParameter( name, type ); else parameter = new SqlParameter( name, type, size ); parameter.Value = value ?? DBNull.Value; parameter.Direction = direction; parameters.Add( parameter ); } #endregion

Como puede ver, dentro de ese método (y sobrecargas), donde el valor ya está escrito como un objeto, uso la declaración "value ?? DBNull.Value" para aplicar la regla null = DBNull.Value.

Ahora, cuando pasa referencias a objetos nulos o tipos anulables sin valores a su método AddParameter, obtiene el comportamiento intuitivo esperado, donde se pasa un valor DBNull.Value a la consulta.

No puedo imaginar por qué se implementó la API tal como está, porque si quisiera que se ignorara un parámetro, no lo AGREGARÍA y luego ESTABLECERía su valor a nulo. O bien NO lo agregaría en primer lugar, o ME QUITARÍA de la colección SqlParameterCollection. Si AGREGO un parámetro, y AJUSTE su valor (incluso si se establece en nulo), espero que SE UTILICE en la consulta, espero que nulo signifique valor nulo.

He oído que no lo implementaron de la manera "correcta" por razones de rendimiento, pero eso es ridículo, como se demostró, porque al llamar al método SqlParameterCollection.AddWithValue todo se convierte en un objeto de todos modos, y convertir una instancia de Nullable sin valor a un valor nulo objeto es una parte intrínseca del lenguaje C # que no es un éxito de rendimiento en absoluto. Microsoft realmente debería arreglar esto.