it-swarm-id.com

SqlParameter sudah dimuat oleh SqlParameterCollection lain - Apakah menggunakan cheat () {}?

Saat menggunakan blok using() {} (sic) seperti yang ditunjukkan di bawah ini, dan dengan asumsi bahwa cmd1 tidak hidup di luar lingkup blok using() {} pertama, mengapa blok kedua harus membuat pengecualian dengan pesan tersebut 

SqlParameter sudah dimuat oleh SqlParameterCollection lainnya

Apakah ini berarti bahwa sumber daya dan/atau pegangan - termasuk parameter (SqlParameterCollection) - yang dilampirkan ke cmd1 tidak dirilis ketika dihancurkan pada akhir blok?

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);
        }
    }
}

CATATAN: Melakukan cmd1.Parameters.Clear () tepat sebelum tanda kurung terakhir dari using () {} blok akan menyelamatkan Anda dari pengecualian (dan kemungkinan memalukan).

Jika Anda perlu mereproduksi, Anda dapat menggunakan skrip berikut untuk membuat objek:

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

Saya menduga SqlParameter "tahu" perintah mana yang menjadi bagiannya, dan bahwa informasi itu tidak dihapus ketika perintah dibuang, tetapi is dihapus ketika Anda memanggil command.Parameters.Clear().

Secara pribadi saya pikir saya akan menghindari menggunakan kembali benda-benda di tempat pertama, tetapi terserah Anda :)

85
Jon Skeet

Menggunakan blok tidak memastikan bahwa suatu objek "dihancurkan", hanya saja metode Dispose() dipanggil. Apa yang sebenarnya dilakukan tergantung pada implementasi spesifik dan dalam hal ini jelas tidak mengosongkan koleksi. Idenya adalah untuk memastikan bahwa sumber daya yang tidak dikelola yang tidak akan dibersihkan oleh pengumpul sampah dibuang dengan benar. Karena pengumpulan Parameter bukan sumber daya yang tidak dikelola, tidak sepenuhnya mengejutkan itu tidak dibersihkan dengan metode buang.

8
Ben Robinson

Menambahkan cmd.Parameters.Clear (); setelah eksekusi harus baik-baik saja.

4
Nish

using mendefinisikan ruang lingkup, dan melakukan panggilan otomatis Dispose() yang kami sukai.

Referensi yang keluar dari ruang lingkup tidak akan membuat objek itu sendiri "menghilang" jika objek lain memiliki referensi padanya, yang dalam kasus ini akan menjadi kasus untuk parameters memiliki referensi ke cmd1.

3
Jon Hanna

Saya juga mendapat masalah yang sama Terima kasih @ Jon, berdasarkan itu saya berikan contoh.

Ketika saya memanggil fungsi di bawah ini di mana 2 kali sqlparameter yang sama berlalu. Dalam panggilan basis data pertama, itu dipanggil dengan benar, tetapi di kedua kalinya, itu memberikan kesalahan di atas.

    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;
    }

Ini adalah fungsi DAL umum

       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

Saya menghadapi kesalahan khusus ini karena saya menggunakan objek SqlParameter yang sama sebagai bagian dari koleksi SqlParameter untuk memanggil prosedur beberapa kali. Alasan untuk kesalahan ini IMHO adalah bahwa objek SqlParameter terkait dengan Koleksi SqlParameter tertentu dan Anda tidak dapat menggunakan objek SqlParameter yang sama untuk membuat koleksi SqlParameter baru. 

Jadi, bukannya - 

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

var param2 = SqlParameter baru {DbType = DbType.Int64, ParameterName = param2, Direction = ParameterDirection.Input, Nilai = 100}; 

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

ExecuteProc (sp_name, sqlParameter1);

/ * GALAT: 

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

ExecuteProc (sp_name, sqlParameter2);

* / 

Melakukan hal ini- 

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

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

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

1
SaCh

Isu
Saya menjalankan prosedur yang tersimpan SQL Server dari C # ketika saya mengalami masalah ini: 

Pesan pengecualian [SqlParameter sudah terkandung oleh SqlParameterCollection lain.]

Sebab
Saya memberikan 3 parameter ke prosedur tersimpan saya. Saya menambahkan 

param = command.CreateParameter();

hanya sekali sekaligus. Saya seharusnya menambahkan baris ini untuk setiap parameter, artinya 3 kali sekaligus. 

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);

Solusi
Menambahkan baris kode berikut untuk setiap parameter

param = command.CreateParameter();
0
Goldfish

Saya menemukan pengecualian ini karena saya gagal instantiate objek parameter. Saya pikir itu mengeluh tentang dua prosedur yang memiliki parameter dengan nama yang sama. Itu mengeluh tentang parameter yang sama yang ditambahkan dua kali.

            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