2011-11-16 25 views
9

estoy tomando datos que se encuentra en una List de Record objetos y poner su contenido en una base de datos:C# SqlParameters Mano corto

// Processes a Record and adds it to the database 
public bool addRecord(SqlConnection db, List<Record> recordsToAdd) 
{ 
    using (SqlCommand command = db.CreateCommand()) 
    { 
     foreach (Record record in recordsToAdd) 
     { 
      // Set the query command text 
      command.CommandText = @"INSERT INTO SMDGROUP_STPRODMASTER (PRODCODE, TOTFREE, TOTPHYS, ITEMTYPE, PRODESC) VALUES ('@PRODCODE', '@TOTFREE', '@TOTPHYS', '@ITEMTYPE', '@PRODESC')"; 

      SqlParameter param1 = new SqlParameter("@CURSTAT", record.curstat); 
      SqlParameter param2 = new SqlParameter("@ITEMDESC", record.itemdesc); 
      SqlParameter param3 = new SqlParameter("@PRODCODE", record.prodcode); 
      SqlParameter param4 = new SqlParameter("@TOTFREE", record.totfree); 
      SqlParameter param5 = new SqlParameter("@TOTPHYS", record.totphys); 
      SqlParameter param6 = new SqlParameter("@ITEMTYPE", record.itemtype); 
      SqlParameter param7 = new SqlParameter("@PRODESC", record.proddesc); 

      command.Parameters.Add(param1); 
      command.Parameters.Add(param2); 
      command.Parameters.Add(param3); 
      command.Parameters.Add(param4); 
      command.Parameters.Add(param5); 
      command.Parameters.Add(param6); 
      command.Parameters.Add(param7); 

      // Execute the query 
      command.ExecuteNonQuery(); 
     } 
     return true; 
    } 
} 

Aquí está mi clase Record:

class Record 
{ 
    public string curstat { get; set; } 
    public string itemtype { get; set; } 
    public string itemdesc { get; set; } 
    public string prodcode { get; set; } 
    public string proddesc { get; set; } 
    public string totfree { get; set; } 
    public string totphys { get; set; } 
} 

Sólo a partir de mirando el código, tengo la sensación de que hay una forma más corta de lograr esto.

Pero en segundo lugar, ni siquiera estoy seguro de haberlo hecho correctamente, de que los valores @PARAMETER están siendo reemplazados.

Si veo el contenido de command, todavía muestra la cadena de consulta con los parámetros @.

Además, estoy recibiendo este error en command.ExecuteNonQuery():

Cadena o datos binarios podrían truncarse.

La declaración ha finalizado.

Por lo tanto, mis preguntas son:

  • ¿Hay un camino más corto para establecer y añadir varios parámetros a la consulta?
  • ¿Qué podría estar causando el error?
+1

¿Cuál es la definición de su tipo de registro? –

+2

El error probablemente se deba a que intenta insertar datos en una columna que no es lo suficientemente grande como para almacenarlo. Por ejemplo, tratar de almacenar 'abcdef' en un' varchar (5) 'causaría este error. –

+0

¡He agregado la clase a la pregunta ahora, gracias! – Luke

Respuesta

15

Usted tiene un constructor más grande:

command.Parameters.Add(
    "@CategoryName", SqlDbType.VarChar, 80).Value = "toasters"; 
+1

El beneficio de este enfoque es que truncarán los datos al tamaño de datos especificado y teclear –

+2

La desventaja de este enfoque es que va a corromper silenciosamente tus datos sin previo aviso. No estoy de acuerdo con el enfoque que Microsoft tomó sobre esto. Realmente debería arrojar una excepción, no truncar silenciosamente sus datos. –

6

Utilizando el método AddWithValue hará que el código un poco más corto:

command.Parameters.AddWithValue("@CURSTAT", record.curstat); 
//... 
+2

Debería verificar [¿Podemos dejar de usar AddWithValue() ya?] (Http://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/) y deje de usar '.AddWithValue()' - puede generar resultados inesperados y sorprendentes ... –

1

En lo que respecta al error, es un problema de truncamiento es decir, la longitud de su parámetro es más larga de lo que puede contener su columna. Para resolver esto, sea más específico al pasar sus parámetros, p. new SqlParameter("@MyParameter", SqlDbType.VarChar, 30).

Personalmente, no creo que tengan nada de malo en la forma en que su adición actual de los parámetros es legible y hace el trabajo. Sin embargo, si desea reducir la cantidad de líneas de código en su función, puede ir con lo que @Royi ha sugerido o simplemente empaquetar el parámetro agregando en otro método.

+0

En realidad, la respuesta de Tim es más correcta. Esa excepción no se trata del tamaño del parámetro, sino del tamaño de la columna. –

+0

@BrandonMoore - Si lee mi respuesta, declaro claramente 'su columna espera menos caracteres de los que su parámetro está dando', es decir, los datos del parámetro están desbordando el tamaño de la columna. Es la misma respuesta redactada de manera diferente: la actualicé para ser aún más clara. – James

+0

Bastante justo. Me centré en la parte sobre "Para evitar esto, debería ser más específico al pasar sus parámetros". –

2

String or binary data would be truncated. lo más probable es que pongas demasiados caracteres en uno de tus campos de VARCHAR. Es decir, si su columna PRODDESC es una VARCHAR (50), y la cadena que está tratando de insertar es de 70 caracteres, verá ese error.

Otros han abordado formas alternativas de hacer los parámetros para que pueda reducir las líneas de código.

3

Lo hago de forma un poco diferente.

Tengo tanto un método de extensión como un método estático para crear SqlParameters.

public static SqlParameter ToParam(this object v,string name){ 
return new SqlParameter(name,v); 
} 

Entonces hacer algo como esto:

var p = new List<SqlParameter>(); 
p.Add(record.curstat.ToParam("@curstat")); 
p.Add(record.itemdesc.ToParam("@itemdesc")); 
//etc... 

command.Parameters.AddRange(p.ToList()); 
1

Para una sintaxis más corta, puede utilizar AddRange método de la clase SqlParameterCollection. Significa:

command.Parameters.AddRange(new [] { 
    new SqlParameter(...), 
    new SqlParameter(...), 
    new SqlParameter(...) }); 

El error que está recibiendo indica que un valor de cadena no encaja en la columna o parámetro de la mesa, y se está truncado. Debe verificar la longitud de la columna en comparación con los datos que se insertan, o especificar la longitud de los parámetros utilizando otra sobrecarga del constructor SqlParameter.

0

Si desea utilizar la clase siguiente:

Class MyParam 
{ 
    public string name {get;set;} 
    public object value {get;set;} 
} 

entonces usted podría tener una lista de llamadas myParams y hacer:

foreach(var p in myParams) command.Parameters.AddWithValue(p.name, p.value); 

Usted, evidentemente, tienen que enlazar los parámetros y valores de alguna manera y no hay no hay forma de evitar eso. Pero si lo haces en una clase como esta, entonces el código que realmente hace la acción es solo de una línea de longitud.

0

Creo que el mensaje

String or binary data would be truncated. 

The statement has been terminated. 

proviene de un error en el texto de comando: en la consulta SQL los parámetros, incluso si son cadenas, no necesita ser citado.

sustituir el comando con este

command.CommandText = @"INSERT INTO SMDGROUP_STPRODMASTER 
     (PRODCODE, TOTFREE, TOTPHYS, ITEMTYPE, PRODESC) 
     VALUES (@PRODCODE, @TOTFREE, @TOTPHYS, @ITEMTYPE, @PRODESC)"; 

Para acortar el código Creo que se podría añadir algún lugar (por ejemplo, en la clase de registro o en una clase de ayuda) un método que crea una matriz de parámetros de un registro objeto y luego llamar a la función AddRange. Debería mantener esta función más limpia y también podría usarla en otra parte de su código.