Evitar el error sql parameter contained by another SqlParameterCollection / Otro SqlParameterCollection ya contiene SqlParameter.

Este error se suele producir cuando trabajamos por ejemplo con Stored Procedures con parámetros.

 

El error nos aparece así en el Visual Studio:

Error

Esto sucede porque cuando asignamos un SqlParameter a dos SqlParameterCollection, por ejemplo de dos SqlCommand diferentes, se produce una asociación con esta SqlParameterCollection, impidiendo que podamos asignar el mismo SqlParameter a otra SqlParameterCollection.

 

Este error no lo solucionaremos con la clausula Using, sino con un Clear() de la SqlparameterCollection, justo después de haberlo utilizado.

Lo voy a ilustrar con un ejemplo que nos permitirá reproducir el error.

Supongamos que tenemos un programa que llama dos veces a un procedimiento almacenado en una clase que tenemos desarrollada y que escribe el resultado en la consola.

El programa Main, que llama dos veces al procedimiento almacenado para que se produzca el error sería el siguiente:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;

namespace UsingCommand
{
    class Program
    {
        static void Main(string[] args)
        {
            CoreCommands comandos = new CoreCommands();

            List<SqlParameter> parametros = new List<SqlParameter>();

            parametros.Add(new SqlParameter("EmployeeID","1"));

            comandos.ExecuteDataReader_SP_Reader("GetEmployeebyID", parametros);

            comandos.ExecuteDataReader_SP_Reader("GetEmployeebyID", parametros);

            Console.ReadLine();
        }
    }
}

 

En la segunda llamada de    comandos.ExecuteDataReader_SP_Reader("GetEmployeebyID", parametros);  se produciría el error

 

Ahora os pongo la clase a la que se invoca desde MAIN con un método ExecuteDataReader_SP_Reader que provocaría el error:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace UsingCommand
{
    class CoreCommands
    {

        public void VisualizarDataReader(SqlDataReader reader)
        {
                while (reader.Read())
            {
                 for (int x=0; x<reader.FieldCount;x++){
                     Console.WriteLine(reader.GetValue(x).ToString());
                }
                }
        }

public void  ExecuteDataReader_SP_Reader(string SPname, List<SqlParameter> parametros)
       {
           using (SqlConnection conexion = new SqlConnection())
           {
               conexion.ConnectionString = "Data Source=.\MSSQL2008STD;Initial Catalog=AdventureWorks;Integrated Security=SSPI;";
               conexion.Open();

               using (SqlCommand comando = new SqlCommand())
               {
                   comando.Connection = conexion;
                   comando.CommandType = System.Data.CommandType.StoredProcedure;
                   comando.CommandText = SPname;
                   comando.Parameters.Clear();

                   foreach (SqlParameter parametro in parametros)
                   {
                       comando.Parameters.Add(parametro);
                   }

                   SqlDataReader lector = comando.ExecuteReader();
                   VisualizarDataReader(lector);

               }
           }

       }

}

}

Esta clase, con su función DataTable ExecuteTABLE_SP_Reader(string SPname, List<SqlParameter> parametros) provocaría un error, pese a estar tanto el objeto conexion como el command bajo la claúsula “using”.

También hemos puesto el Clear(), pero para que funcione debemos ponerlo después de utilizar el comando.

Para que no se produzca el error, la función ExecuteTABLE_SP_Reader debería hacer el Clear() después de haber utilizado el SqlCommand:

public void  ExecuteDataReader_SP_Reader(string SPname, List<SqlParameter> parametros)
       {
           using (SqlConnection conexion = new SqlConnection())
           {
               conexion.ConnectionString = "Data Source=.\MSSQL2008STD;Initial Catalog=AdventureWorks;Integrated Security=SSPI;";
               conexion.Open();

               using (SqlCommand comando = new SqlCommand())
               {
                   comando.Connection = conexion;
                   comando.CommandType = System.Data.CommandType.StoredProcedure;
                   comando.CommandText = SPname;

                   foreach (SqlParameter parametro in parametros)
                   {
                       comando.Parameters.Add(parametro);
                   }

                   SqlDataReader lector = comando.ExecuteReader();
                   VisualizarDataReader(lector);
                   comando.Parameters.Clear();
               }
           }

       }

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *