【问题标题】:ASP, The SqlParameter is already contained by another SqlParameterCollectionASP,SqlParameter 已被另一个 SqlParameterCollection 包含
【发布时间】:2017-10-17 08:12:14
【问题描述】:

在我的应用程序中执行 SQL Server 存储过程时遇到问题。我以前没有遇到过这个问题。

我的数据类是:

public static string conStr
{
    get { return ConfigurationManager.ConnectionStrings["conn"].ConnectionString; }
}

public static string Provider
{
    get { return ConfigurationManager.ConnectionStrings["conn"].ProviderName; } //Proveedor de DB
}

//DB PROVIDER FACTORY: Objetos de Conexion
public static System.Data.Common.DbProviderFactory dpf
{
    get { return DbProviderFactories.GetFactory(Provider); }
}

private static int ejecutaNonQuery(string StoredProcedure, List<DbParameter> parametros)
{//execute nonquery retorna el numero de columnas afectadas en una dB 
    int Id = 0; //variable para saber cuantos elementos se modificaron despues del ejecutenonquery

    try
    {
        using (DbConnection con = dpf.CreateConnection()) //al usar using la conexion se cerrara automaticamente
        {
            con.ConnectionString = conStr;
            using (DbCommand cmd = dpf.CreateCommand())
            {
                cmd.Connection = con;
                cmd.CommandText = StoredProcedure;
                cmd.CommandType = CommandType.StoredProcedure;

                foreach (DbParameter param in parametros)
                    cmd.Parameters.Add(param);

                con.Open();
                Id = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear(); 
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    { }

    return Id;
}

这是执行:

public int Lotes_Crear_Consolidado(string cliCodigo, string cajCodigo, int cajNumero, 
                                   int cajConNumero, string cajConCodigo,
                                   string id1Desde, string id1Hasta, 
                                   string id2Desde, string id2Hasta,
                                   string id3Desde, string id3Hasta,
                                   string id4Desde, string id4Hasta,
                                   string id5Desde, string id5Hasta,
                                   string altaPor, string lotEstado, 
                                   DateTime fecEmiLot, DateTime fecCadLot)
{
    List<DbParameter> paramLotesConsol = new List<DbParameter>();

    DbParameter param1 = dpf.CreateParameter();
    param1.DbType = DbType.String;
    param1.Value = cliCodigo;
    param1.ParameterName = "CLIENTE_CODIGO";
    paramLotesConsol.Add(param1);

    DbParameter param2 = dpf.CreateParameter();
    param2.DbType = DbType.String;
    param2.Value = cajCodigo;
    param2.ParameterName = "CAJA_CODIGO";
    paramLotesConsol.Add(param2);

    DbParameter param3 = dpf.CreateParameter();
    param3.DbType = DbType.Int16;
    param3.Value = cajNumero;
    param3.ParameterName = "CAJA_NUMERO";
    paramLotesConsol.Add(param3);

    DbParameter param4 = dpf.CreateParameter();
    param4.DbType = DbType.Int16;
    param4.Value = cajConNumero;
    param4.ParameterName = "CAJA_CONTENIDO_NUMERO";
    paramLotesConsol.Add(param4);

    DbParameter param5 = dpf.CreateParameter();
    param5.DbType = DbType.String;
    param5.Value = cajConCodigo;
    param5.ParameterName = "CAJA_CONTENIDO_CODIGO";
    paramLotesConsol.Add(param5);

    DbParameter param6 = dpf.CreateParameter();
    param6.DbType = DbType.String;
    param6.Value = id1Desde;
    param6.ParameterName = "ID1_DESDE";
    paramLotesConsol.Add(param6);

    DbParameter param7 = dpf.CreateParameter();
    param7.DbType = DbType.String;
    param7.Value = id1Hasta;
    param7.ParameterName = "ID1_HASTA";
    paramLotesConsol.Add(param7);

    DbParameter param8 = dpf.CreateParameter();
    param8.DbType = DbType.String;
    param8.Value = id2Desde;
    param8.ParameterName = "ID2_DESDE";
    paramLotesConsol.Add(param8);

    DbParameter param9 = dpf.CreateParameter();
    param9.DbType = DbType.String;
    param9.Value = id2Hasta;
    param9.ParameterName = "ID2_HASTA";
    paramLotesConsol.Add(param9);

    ........

    DbParameter param26 = dpf.CreateParameter();
    param26.DbType = DbType.String;
    param26.Value = altaPor;
    param26.ParameterName = "ALTA_POR";
    paramLotesConsol.Add(param26);

    DbParameter param27 = dpf.CreateParameter();
    param27.DbType = DbType.String;
    param27.Value = lotEstado;
    param27.ParameterName = "ESTADO";
    paramLotesConsol.Add(param27);

    DbParameter param28 = dpf.CreateParameter();
    param28.DbType = DbType.Date;
    param28.Value = fecEmiLot;
    param28.ParameterName = "FECHA_EMISION_LOTE";
    paramLotesConsol.Add(param28);

    DbParameter param29 = dpf.CreateParameter();
    param29.DbType = DbType.Date;
    param29.Value = fecCadLot;
    param29.ParameterName = "FECHA_CADUCID_LOTE";
    paramLotesConsol.Add(param29);

    return ejecutaNonQuery("LOTES_CREAR_CONSOLIDADO", paramLotesConsol);
}

那我这样称呼它:

Caja_Contenido_BL loteBL = new Caja_Contenido_BL();

我必须将来自 gridview 的数据插入到我的数据库中,因此我在每一行上运行用于插入数据的存储过程。

我得到的错误是:

SqlParameter 已被另一个 SqlParameterCollection 包含

代码:

protected void Lotes_Crear_Consolidado(object sender, EventArgs e)
{
    string altaPor = User.Identity.Name.ToString().ToUpper();

    foreach (GridViewRow grdCajUpd_Row in this.gvwLotConsol_Plant.Rows)
    {
        string cliCod = Convert.ToString(grdCajUpd_Row.Cells[0].Text);
        string cajCod = Convert.ToString(grdCajUpd_Row.Cells[1].Text);
        int cajNum = Convert.ToInt16(grdCajUpd_Row.Cells[2].Text);
        int cajConNum = Convert.ToInt16(grdCajUpd_Row.Cells[3].Text);
        string cajConCod = Convert.ToString(grdCajUpd_Row.Cells[4].Text);

        string id1Desde = Convert.ToString(grdCajUpd_Row.Cells[5].Text);
        string id1Hasta = Convert.ToString(grdCajUpd_Row.Cells[6].Text);
        string id2Desde = Convert.ToString(grdCajUpd_Row.Cells[7].Text);
        string id2Hasta = Convert.ToString(grdCajUpd_Row.Cells[8].Text);
        string id3Desde = Convert.ToString(grdCajUpd_Row.Cells[9].Text);
        string id3Hasta = Convert.ToString(grdCajUpd_Row.Cells[10].Text);
        string id4Desde = Convert.ToString(grdCajUpd_Row.Cells[11].Text);
        string id4Hasta = Convert.ToString(grdCajUpd_Row.Cells[12].Text);
        string id5Desde = Convert.ToString(grdCajUpd_Row.Cells[13].Text);
        string id5Hasta = Convert.ToString(grdCajUpd_Row.Cells[14].Text);
        string id6Desde = Convert.ToString(grdCajUpd_Row.Cells[15].Text);
        string id6Hasta = Convert.ToString(grdCajUpd_Row.Cells[16].Text);
        string id7Desde = Convert.ToString(grdCajUpd_Row.Cells[17].Text);
        string id7Hasta = Convert.ToString(grdCajUpd_Row.Cells[18].Text);
        string id8Desde = Convert.ToString(grdCajUpd_Row.Cells[19].Text);
        string id8Hasta = Convert.ToString(grdCajUpd_Row.Cells[20].Text);
        string id9Desde = Convert.ToString(grdCajUpd_Row.Cells[21].Text);
        string id9Hasta = Convert.ToString(grdCajUpd_Row.Cells[22].Text);
        string id10Desde = Convert.ToString(grdCajUpd_Row.Cells[23].Text);
        string id10Hasta = Convert.ToString(grdCajUpd_Row.Cells[24].Text);
        string estado = Convert.ToString(grdCajUpd_Row.Cells[25].Text);
        DateTime fecEmiLot = Convert.ToDateTime(grdCajUpd_Row.Cells[26].Text);
        DateTime fecCadLot = Convert.ToDateTime(grdCajUpd_Row.Cells[27].Text);

        loteBL.Lotes_Crear_Consolidado(cliCod, cajCod, cajNum, cajConNum, cajConCod,
            id1Desde, id1Hasta, id2Desde, id2Hasta, id3Desde, id3Hasta, id4Desde, id4Hasta,
            id5Desde, id5Hasta, id6Desde, id6Hasta, id7Desde, id7Hasta, id8Desde, id8Hasta,
            id9Desde, id9Hasta, id10Desde, id10Hasta, altaPor, estado, fecEmiLot, fecCadLot);

    }
    Page.ClientScript.RegisterStartupScript(this.GetType(), "AlertScript", "alert('Lote(s) Creado(s)!');", true);
}

我用cmd.Parameters.Clear()清除命令参数。

在 SQL Server 中,我在其他存储过程的 SQL 参数中使用相同的名称。 不知道是什么问题。

如果有人可以帮助我,我将不胜感激

最好的问候

【问题讨论】:

  • 异常发生在哪一行?我的第一个想法是使用所有名为 paramXX 的变量,您要添加两次。
  • Parameters.Clear() 在哪里?我通常会在执行命令后立即执行,然后将命令本身处理掉。
  • 旁注:1)如果您不处理异常(您所做的只是重新抛出)并且 finally 是空的,那么将 try/catch/finally 一起删除,它只会给您的代码和潜在的错误。 2) 前一点的例子,并且永远不会通过传入异常来重新抛出异常,即:throw ex; 应该读为throw;。前者重置调用堆栈,使以后的故障排除变得更加困难,后者保留调用堆栈。
  • 其他注释 -- 1)TableCell.Text 本身返回string 时,为什么需要调用Convert.ToString2) 我强烈建议创建一个元数据类,它包含目标类型、数据库类型,也许还有一个名称(仅用于调试目的)。然后,实例化并填充这些类的List。最后,您可以使用该列表来构建一系列 DB 参数实例,您可以依次将其添加到存储过程中。

标签: c# asp.net sql-server


【解决方案1】:

您只能使用一次 SqlParameter。由于您将 SqlParameters 传递给方法,我假设它们也在其他地方使用?

如果您希望保留呼叫签名并希望快速修复,请尝试此操作。而不是

foreach (DbParameter param in parametros)
    cmd.Parameters.Add(param);

试试

foreach (ICloneable param in parametros)
    cmd.Parameters.Add(param.Clone() as SqlParameter);

【讨论】:

  • 一个参数绝对可以多次使用;它不能同时是多个参数集合的成员。
【解决方案2】:

感谢大家的帮助。 这是我的错误,我处理了近 30 个参数,其中一个是重复的。 对不起...

有谁知道如何删除这篇文章?

再次感谢!

【讨论】:

    【解决方案3】:

    如果我没记错的话,您需要编辑帖子才能删除它。为避免此类问题,我建议创建一个这样的辅助函数:

    private void AddParameter(DbProviderFactory dpf, List<DbParameter> params, DbType type, object value, string name)
    {
        DbParameter param = dpf.CreateParameter();
        param.DbType = type;
        param.Value = value;
        param.ParameterName = name;
        params.Add(param);
    }
    

    然后这样称呼它:

     AddParameter(dpf, paramLotesConsol, DbType.String, cliCodigo, "CLIENTE_CODIGO");
     AddParameter(dpf, paramLotesConsol, DbType.String, cajCodigo, "CAJA_CODIGO");
    // etc.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-11
      • 2011-09-11
      • 1970-01-01
      • 2019-04-10
      • 2012-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多