sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cuál es el mejor método para pasar parámetros a SQLCommand?

¿Qué está pasando allí?

Citas las listas de parámetros para varias sobrecargas de Add . Estos son métodos convenientes que corresponden directamente a sobrecargas de constructores para SqlParameter clase. Básicamente, construyen el objeto de parámetro utilizando cualquier constructor que tenga la misma firma que el método de conveniencia que llamó y luego llaman a SqlParameterCollection.Add(SqlParameter) así:

SqlParameter foo = new SqlParameter(parameterName, dbType, size);
this.Add(foo);

AddWithValue es similar pero lleva la conveniencia aún más allá, también establece el valor. Sin embargo, en realidad se introdujo para resolver una falla del marco. Para citar a MSDN,

La sobrecarga de Add que toma una cadena y un objeto quedó en desuso debido a una posible ambigüedad con SqlParameterCollection.Add sobrecarga que toma una String y un SqlDbType valor de enumeración donde pasar un número entero con la cadena podría interpretarse como el valor del parámetro o el SqlDbType correspondiente valor. Utilice AddWithValue cada vez que desee agregar un parámetro especificando su nombre y valor.

El constructor se sobrecarga para el SqlParameter class son meras conveniencias para establecer propiedades de instancia. Acortan el código, con un impacto marginal en el rendimiento:el constructor puede pasar por alto los métodos de establecimiento y operar directamente en miembros privados. Si hay una diferencia, no será mucha.

¿Qué debo hacer?

Tenga en cuenta lo siguiente (de MSDN)

Para parámetros bidireccionales y de salida, y valores de retorno, debe establecer el valor de Size . Esto no es necesario para los parámetros de entrada y, si no se establece explícitamente, el valor se deduce del tamaño real del parámetro especificado cuando se ejecuta una instrucción parametrizada.

El tipo predeterminado es entrada. Sin embargo, si permite que el tamaño se infiera de esta manera y recicla el objeto de parámetro en un bucle (dijo que estaba preocupado por el rendimiento), entonces el tamaño se establecerá por el primer valor y cualquier valor posterior que sea más largo será cortado. Obviamente, esto es significativo solo para valores de longitud variable, como cadenas.

Si está pasando el mismo parámetro lógico repetidamente en un bucle, le recomiendo que cree un objeto SqlParameter fuera del bucle y le dé el tamaño adecuado. Sobredimensionar un varchar es inofensivo, por lo que si es un PITA para obtener el máximo exacto, simplemente configúrelo más grande de lo que esperaba que fuera la columna. Debido a que está reciclando el objeto en lugar de crear uno nuevo para cada iteración, es probable que el consumo de memoria durante la duración del ciclo disminuya incluso si te emocionas un poco con el tamaño grande.

A decir verdad, a menos que proceses miles de llamadas, nada de esto hará mucha diferencia. AddWithValue crea un nuevo objeto, eludiendo el problema de tamaño. Es corto, dulce y fácil de entender. Si recorre miles, use mi enfoque. Si no lo hace, use AddWithValue para mantener su código simple y fácil de mantener.

2008 fue hace mucho tiempo

En los años transcurridos desde que escribí esto, el mundo ha cambiado. Hay nuevos tipos de fechas, y también hay un problema que no se me pasó por la cabeza hasta que un problema reciente con las fechas me hizo pensar en las implicaciones de la ampliación.

Ensanchar y estrechar, para aquellos que no están familiarizados con los términos, son cualidades de las conversiones de tipos de datos. Si asigna un int a un doble, no hay pérdida de precisión porque el doble es "más ancho". Siempre es seguro hacer esto, por lo que la conversión es automática. Esta es la razón por la que puede asignar un int a un doble, pero al revés, debe hacer un lanzamiento explícito:doble a int es una conversión de restricción con una posible pérdida de precisión.

Esto se puede aplicar a las cadenas:NVARCHAR es más ancho que VARCHAR, por lo que puede asignar un VARCHAR a un NVARCHAR, pero ir en sentido contrario requiere una conversión. La comparación funciona porque VARCHAR se amplía implícitamente a NVARCHAR, ¡pero esto interferirá con el uso de índices!

Las cadenas de C# son Unicode, por lo que AddWithValue generará un parámetro NVARCHAR. En el otro extremo, los valores de la columna VARCHAR se amplían a NVARCHAR para comparar. Esto no detiene la ejecución de consultas, pero evita que se utilicen índices. Esto es malo.

¿Qué puedes hacer al respecto? Tienes dos soluciones posibles.

  • Escriba explícitamente el parámetro. Esto significa que no más AddWithValue
  • Cambie todos los tipos de columnas de cadena a NVARCHAR.

Abandonar VARCHAR es probablemente la mejor idea. Es un cambio simple con consecuencias predecibles y mejora su historia de localización. Sin embargo, es posible que no tenga esto como una opción.

En estos días no hago mucho ADO.NET directo. Linq2Sql es ahora mi arma preferida, y el acto de escribir esta actualización me ha dejado preguntándome cómo manejará este problema. Tengo un deseo repentino y ardiente de verificar mi código de acceso a datos para buscar a través de columnas VARCHAR.

2019 y el mundo ha avanzado otra vez

Linq2Sql no está disponible en dotnet Core, por lo que me encuentro usando Dapper. El problema [N]VARCHAR sigue existiendo, pero ya no está tan enterrado. Creo que también se puede usar ADO, por lo que las cosas han dado un giro completo en ese sentido.