it-swarm.com.de

Der SqlParameter ist bereits in einem anderen SqlParameterCollection enthalten.

Bei der Verwendung der using() {} (sic) -Blöcke (siehe unten) und der Annahme, dass cmd1 nicht den Rahmen des ersten using() {}-Blocks überschreitet, sollte der zweite Block eine Ausnahme mit der Nachricht auslösen 

Der SqlParameter ist bereits in einer anderen SqlParameterCollection enthalten

Bedeutet dies, dass Ressourcen und/oder Handles - einschließlich der an cmd1 angehängten Parameter (SqlParameterCollection) - nicht freigegeben werden, wenn sie am Ende des Blocks zerstört werden?

using (var conn = new SqlConnection("Data Source=.;Initial Catalog=Test;Integrated Security=True"))
{
    var parameters = new SqlParameter[] { new SqlParameter("@ProductId", SqlDbType.Int ) };

    using(var cmd1 = new SqlCommand("SELECT ProductName FROM Products WHERE ProductId = @ProductId"))
    {
        foreach (var parameter in parameters)
        {
            cmd1.Parameters.Add(parameter);                
        }
        // cmd1.Parameters.Clear(); // uncomment to save your skin!
    }

    using (var cmd2 = new SqlCommand("SELECT Review FROM ProductReviews WHERE ProductId = @ProductId"))
    {
        foreach (var parameter in parameters)
        {
            cmd2.Parameters.Add(parameter);
        }
    }
}

HINWEIS: Wenn Sie cmd1.Parameters.Clear () kurz vor der letzten Klammer des ersten using () {} - Blocks verwenden, werden Sie vor der Ausnahme (und möglicher Peinlichkeit) geschützt.

Wenn Sie reproduzieren müssen, können Sie die folgenden Skripts zum Erstellen der Objekte verwenden:

CREATE TABLE Products
(
    ProductId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    ProductName nvarchar(32) NOT NULL
)
GO

CREATE TABLE ProductReviews
(
    ReviewId int IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
    ProductId int NOT NULL,
    Review nvarchar(128) NOT NULL
)
GO
67
John Gathogo

Ich vermute, dass SqlParameter "weiß", zu welchem ​​Befehl er gehört, und dass diese Informationen nicht gelöscht werden, wenn der Befehl gelöscht wird, aber ist , wenn Sie command.Parameters.Clear() aufrufen.

Ich persönlich denke, ich würde die Wiederverwendung der Objekte vermeiden, aber es liegt an Ihnen :)

85
Jon Skeet

Durch die Verwendung von Blöcken kann nicht sichergestellt werden, dass ein Objekt "zerstört" wird, es wird lediglich die Dispose()-Methode aufgerufen. Was dies tatsächlich tut, hängt von der konkreten Implementierung ab und in diesem Fall wird die Sammlung offensichtlich nicht entleert. Damit soll sichergestellt werden, dass nicht verwaltete Ressourcen, die nicht vom Garbage Collector entfernt werden, ordnungsgemäß entsorgt werden. Da die Parameters-Sammlung keine nicht verwaltete Ressource ist, ist sie nicht völlig überraschend. Sie wird von der dispose-Methode nicht gelöscht.

8
Ben Robinson

Hinzufügen von cmd.Parameters.Clear (); nach der Ausführung sollte es gut gehen.

4
Nish

using definiert einen Gültigkeitsbereich und führt den automatischen Aufruf von Dispose() aus, für den wir ihn lieben.

Ein außerhalb des Gültigkeitsbereichs liegender Verweis lässt das Objekt selbst nicht "verschwinden", wenn ein anderes Objekt einen Verweis darauf hat, was in diesem Fall der Fall ist, wenn parameters einen Verweis auf cmd1 hat.

3
Jon Hanna

Ich habe auch das selbe Problem bekommen Danke @Jon, basierend darauf habe ich ein Beispiel gegeben.

Als ich die folgende Funktion aufgerufen habe, in der 2 mal der gleiche sqlparameter übergeben wurde. Im ersten Datenbankaufruf wurde es ordnungsgemäß aufgerufen, aber beim zweiten Mal wurde der obige Fehler ausgegeben.

    public Claim GetClaim(long ClaimId)
    {
        string command = "SELECT * FROM tblClaim "
            + " WHERE RecordStatus = 1 and ClaimId = @ClaimId and ClientId [email protected]";
        List<SqlParameter> objLSP_Proc = new List<SqlParameter>(){
                new SqlParameter("@ClientId", SessionModel.ClientId),
                new SqlParameter("@ClaimId", ClaimId)
            };

        DataTable dt = GetDataTable(command, objLSP_Proc);
        if (dt.Rows.Count == 0)
        {
            return null;
        }

        List<Claim> list = TableToList(dt);

        command = "SELECT * FROM tblClaimAttachment WHERE RecordStatus = 1 and ClaimId = @ClaimId and ClientId [email protected]";

        DataTable dt = GetDataTable(command, objLSP_Proc); //gives error here, after add `sqlComm.Parameters.Clear();` in GetDataTable (below) function, the error resolved.


        retClaim.Attachments = new ClaimAttachs().SelectMany(command, objLSP_Proc);
        return retClaim;
    }

Dies ist die gemeinsame DAL-Funktion

       public DataTable GetDataTable(string strSql, List<SqlParameter> parameters)
        {
            DataTable dt = new DataTable();
            try
            {
                using (SqlConnection connection = this.GetConnection())
                {
                    SqlCommand sqlComm = new SqlCommand(strSql, connection);

                    if (parameters != null && parameters.Count > 0)
                    {
                        sqlComm.Parameters.AddRange(parameters.ToArray());
                    }

                    using (SqlDataAdapter da = new SqlDataAdapter())
                    {
                        da.SelectCommand = sqlComm;
                        da.Fill(dt);
                    }
                    sqlComm.Parameters.Clear(); //this added and error resolved
                }
            }
            catch (Exception ex)
            {                   
                throw;
            }
            return dt;
        }
2
Ajay2707

Ich habe diesen besonderen Fehler festgestellt, weil ich dieselben SqlParameter-Objekte als Teil einer SqlParameter-Auflistung verwendet habe, um eine Prozedur mehrmals aufzurufen. Der Grund für diesen Fehler IMHO ist, dass die SqlParameter-Objekte einer bestimmten SqlParameter-Auflistung zugeordnet sind und Sie nicht die gleichen SqlParameter-Objekte zum Erstellen einer neuen SqlParameter-Auflistung verwenden können. 

Also statt - 

var param1 = neuer SqlParameter {DbType = DbType.String, ParameterName = Param1, Direction = ParameterDirection.Input, Value = ""};

var param2 = neuer SqlParameter {DbType = DbType.Int64, ParameterName = Parameter2, Direction = ParameterDirection.Input, Wert = 100}; 

SqlParameter [] sqlParameter1 = new [] {param1, param2};

ExecuteProc (sp_name, sqlParameter1);

/*ERROR : 

SqlParameter [] sqlParameter2 = new [] {param1, param2};

ExecuteProc (sp_name, sqlParameter2);

* / 

Mach das- 

var param3 = neuer SqlParameter {DbType = DbType.String, ParameterName = param1, Direction = ParameterDirection.Input, Value = param1.Value};

var param4 = neuer SqlParameter {DbType = DbType.Int64, ParameterName = param2, Direction = ParameterDirection.Input, Value = param2.Value};

SqlParameter [] sqlParameter3 = new [] {param3, param4}; ExecuteProc (sp_name, sqlParameter3);

1
SaCh

Problem
Ich habe eine gespeicherte SQL Server-Prozedur von C # ausgeführt, als ich auf dieses Problem gestoßen bin: 

Ausnahmemeldung [SqlParameter ist bereits in einer anderen SqlParameterCollection enthalten.]

Ursache
Ich habe 3 Parameter an meine gespeicherte Prozedur übergeben. Ich habe das hinzugefügt 

param = command.CreateParameter();

nur einmal insgesamt. Ich hätte diese Zeile für jeden Parameter hinzufügen sollen, dies bedeutet insgesamt dreimal. 

DbCommand command = CreateCommand(ct.SourceServer, ct.SourceInstance, ct.SourceDatabase);
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "[ETL].[pGenerateScriptToCreateIndex]";

DbParameter param = command.CreateParameter();
param.ParameterName = "@IndexTypeID";
param.DbType = DbType.Int16;
param.Value = 1;
command.Parameters.Add(param);

param = command.CreateParameter(); --This is the line I was missing
param.ParameterName = "@SchemaName";
param.DbType = DbType.String;
param.Value = ct.SourceSchema;
command.Parameters.Add(param);

param = command.CreateParameter(); --This is the line I was missing
param.ParameterName = "@TableName";
param.DbType = DbType.String;
param.Value = ct.SourceDataObjectName;
command.Parameters.Add(param);

dt = ExecuteSelectCommand(command);

Lösung
Hinzufügen der folgenden Codezeile für jeden Parameter

param = command.CreateParameter();
0
Goldfish

Diese Ausnahme ist aufgetreten, weil ein Parameterobjekt nicht instanziiert werden konnte. Ich dachte, es beschwerte sich über zwei Verfahren mit Parametern mit demselben Namen. Es wurde beschwert, dass derselbe Parameter zweimal hinzugefügt wurde.

            Dim aParm As New SqlParameter()
            aParm.ParameterName = "NAR_ID" : aParm.Value = hfCurrentNAR_ID.Value
            m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm)
            aParm = New SqlParameter
            Dim tbxDriveFile As TextBox = gvNetworkFileAccess.Rows(index).FindControl("tbxDriveFolderFile")
            aParm.ParameterName = "DriveFolderFile" : aParm.Value = tbxDriveFile.Text
            m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm)
            **aParm = New SqlParameter()**  <--This line was missing.
            Dim aDDL As DropDownList = gvNetworkFileAccess.Rows(index).FindControl("ddlFileAccess")
            aParm.ParameterName = "AccessGranted" : aParm.Value = aDDL.Text
            **m_daNetworkAccess.UpdateCommand.Parameters.Add(aParm)** <-- The error occurred here.
0
Jon Boy