স্কেলপ্যারামিটারটি ইতিমধ্যে অন্য স্কেলপ্যারামিটার সংগ্রহ দ্বারা অন্তর্ভুক্ত রয়েছে - ()) at চিট ব্যবহার করে?


87

using() {}নীচে দেখানো অনুসারে (sic) ব্লক ব্যবহার করার সময় এবং ধরে cmd1নিলে যে প্রথম using() {}ব্লকের আওতার বাইরে চলে না , দ্বিতীয় ব্লকে বার্তাটি দিয়ে কেন ব্যতিক্রম ছড়িয়ে দেওয়া উচিত?

স্কেলপ্যারামিটারটি ইতিমধ্যে অন্য স্কেলপ্যারামিটার সংগ্রহ দ্বারা অন্তর্ভুক্ত

এর অর্থ কি এই যে ব্লক শেষে ধ্বংস হয়ে SqlParameterCollectionযাওয়ার পরে প্যারামিটারগুলি সহ ) - সংযুক্ত সংস্থানগুলি এবং / অথবা হ্যান্ডলগুলি cmd1প্রকাশিত হয় না?

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

উল্লেখ্য: cmd1.Parameters.Clear করছেন () ঠিক আগে প্রথম থেকে শেষ বক্রবন্ধনী ব্যবহার () {} ব্লক ব্যতিক্রম (এবং সম্ভাব্য অপ্রীতিকর) থেকে আপনি সংরক্ষণ করতে হবে।

আপনার যদি পুনরুত্পাদন করার প্রয়োজন হয় তবে অবজেক্টগুলি তৈরি করতে নিম্নলিখিত স্ক্রিপ্টগুলি ব্যবহার করতে পারেন:

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

আমি এটিও দেখছি, তবে এই ফিক্সটি কার্যকর হয়নি। হতাশাজনক। এবং আমি কেবলমাত্র একটি একক সেমিডি অবজেক্ট ব্যবহার করছি, পুনরায় ব্যবহৃত হয়নি। এটি একটি অ্যাসিঙ্ক পুনরায় চেষ্টা লুপে আবৃত, সুতরাং সম্ভবত এটি একই মূল কারণটি ঠিক একইভাবে এড়ানো সম্ভব নয়।
এড উইলিয়ামস

উত্তর:


111

আমি সন্দেহ যে SqlParameter"জানে" যা তা অংশ আদেশ, এবং যে যে তথ্য সাফ করা হয় যখন কমান্ড বিন্যস্ত হয়, কিন্তু হয় সাফ আপনি কল যখন command.Parameters.Clear()

ব্যক্তিগতভাবে আমি মনে করি আমি প্রথমে জিনিসগুলি পুনরায় ব্যবহার করা এড়াতে চাই, তবে এটি আপনার উপর নির্ভর করে :)


4
ধন্যবাদ আমি সন্দেহ করি যে বিষয়টি। এর অর্থ হ'ল স্কেলপ্যারামিটার নিজেকে কোনও নিষ্পত্তিযোগ্য বস্তুর সাথে সংযুক্ত করছে যা আমি নিশ্চিত নই যে এটি একটি ভাল জিনিস
জন গাথোগো

@ জনগাথোগো: ঠিক আছে, এটি এমন একটি সামগ্রীর সাথে সম্পর্কিত যা সমিতিটি গঠনের পরে নিষ্পত্তি হয়। এটি অবশ্যই আদর্শ নয়।
জন স্কিটি

11
অন্যদের জন্য একটি নোট। Clearপ্রথম usingব্লকটি থেকে বেরিয়ে আসার আগে আমাকে সম্পাদন করতে হয়েছিল । আমার ২ য় usingব্লকে প্রবেশ করার সময় এটি করার পরেও এই ত্রুটিটি ছুঁড়েছে।
স্নেকসে

@ জোনস্কিটটি একই প্যারামিটারগুলির একই সেটটি পুনরায় তৈরি করতে বোকামি, কেবল অন্য কোয়েরি করার জন্য। এটি
দৃ

9

ব্লকগুলি ব্যবহার করে নিশ্চিত করা হয় না যে কোনও বস্তুকে "ধ্বংস" করা হয়েছে, কেবল যে Dispose()পদ্ধতিটি বলা হয়। এটি যা যা করে তা নির্দিষ্ট প্রয়োগের উপর নির্ভর করে এবং এই ক্ষেত্রে এটি পরিষ্কারভাবে সংগ্রহটি খালি করে না। ধারণাটি নিশ্চিত করা হয় যে আবর্জনা সংগ্রহকারী দ্বারা অপরিশোধিত সম্পদগুলি পরিষ্কার করা হবে না তা সঠিকভাবে নিষ্পত্তি করা হয়েছে। যেহেতু প্যারামিটার সংগ্রহগুলি একটি নিয়ন্ত্রণহীন সম্পদ নয় এটি পুরোপুরি আশ্চর্যজনক নয় যে এটি নিষ্পত্তি পদ্ধতিতে সাফ করা হয় না।


7

সেমিডি.প্যারামিটার যুক্ত করা হচ্ছে। ক্লিয়ার (); মৃত্যুদন্ড কার্যকর করার পরে ঠিক করা উচিত।


3

usingএকটি স্কোপ সংজ্ঞায়িত করে, এবং Dispose()যার জন্য আমরা এটি ভালবাসি তার স্বয়ংক্রিয় কলটি করে।

ক্ষেত্রের বাইরে থাকা একটি রেফারেন্স অন্য কোনও বস্তুর সাথে একটি রেফারেন্স থাকলে অবজেক্টটিকে নিজেই "অদৃশ্য হয়ে যাবে" না, যা এই ক্ষেত্রে parametersরেফারেন্স থাকার ক্ষেত্রে হবে cmd1


2

আমি একই সমস্যাটি পেয়েছি ধন্যবাদ @ জন, তার উপর ভিত্তি করে আমি উদাহরণ দিয়েছি।

যখন আমি নীচের ফাংশনটি কল করি যার মধ্যে 2 বার একই স্ক্যাল্পারমিটার উত্তীর্ণ হয়েছিল। প্রথম ডাটাবেস কলে, এটি সঠিকভাবে বলা হয়েছিল, তবে দ্বিতীয়বার এটি উপরের ত্রুটিটি দেওয়া হয়েছিল।

    public Claim GetClaim(long ClaimId)
    {
        string command = "SELECT * FROM tblClaim "
            + " WHERE RecordStatus = 1 and ClaimId = @ClaimId and ClientId =@ClientId";
        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 =@ClientId";

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

এটি সাধারণ ডাল ফাংশন

       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

আমি এই বিশেষ ত্রুটির মুখোমুখি হয়েছি কারণ আমি একাধিকবার কোনও প্রক্রিয়া কল করার জন্য স্কেলপ্যারামিটার সংগ্রহের অংশ হিসাবে একই স্কেলপ্যারামিটার অবজেক্টগুলি ব্যবহার করছিলাম। এই ত্রুটি আইএমএইচওর কারণ হ'ল স্ক্যেলপ্যারামিটার অবজেক্টগুলি একটি নির্দিষ্ট স্ক্লালপ্যারামিটার সংকলনের সাথে সম্পর্কিত এবং আপনি একটি নতুন স্কেলপ্যারামিটার সংগ্রহ তৈরি করতে একই স্কেলপ্ল্যারামিটার অবজেক্টগুলি ব্যবহার করতে পারবেন না।

সুতরাং, এর পরিবর্তে:

var param1 = new SqlParameter{ DbType = DbType.String, ParameterName = param1,Direction = ParameterDirection.Input , Value = "" };
var param2 = new SqlParameter{ DbType = DbType.Int64, ParameterName = param2, Direction = ParameterDirection.Input , Value = 100};

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

ExecuteProc(sp_name, sqlParameter1);

/*ERROR : 
SqlParameter[] sqlParameter2 = new[] { param1, param2 };
ExecuteProc(sp_name, sqlParameter2);
*/ 

এটা কর:

var param3 = new SqlParameter{ DbType = DbType.String, ParameterName = param1, Direction = ParameterDirection.Input , Value = param1.Value };
var param4 = new SqlParameter{ DbType = DbType.Int64, ParameterName = param2, Direction = ParameterDirection.Input , Value = param2.Value};

SqlParameter[] sqlParameter3 = new[] { param3, param4 };

ExecuteProc(sp_name, sqlParameter3);

0

আমি এই ব্যতিক্রমটির মুখোমুখি হয়েছি কারণ আমি প্যারামিটার অবজেক্টটি ইনস্ট্যান্ট করতে ব্যর্থ হয়েছি। আমি ভেবেছিলাম এটি একই নামের পরামিতিগুলির দুটি পদ্ধতি সম্পর্কে অভিযোগ করছে। একই প্যারামিটারটি দু'বার যুক্ত হওয়ার অভিযোগ ছিল।

            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

ইস্যু
আমি সি # থেকে একটি SQL সার্ভার সঞ্চিত পদ্ধতি নির্বাহ হয় যখন আমি এই বিষয় সম্মুখীন হয়েছে:

ব্যতিক্রম বার্তা [স্কেলপ্যারামিটার ইতিমধ্যে অন্য স্কেলপ্যারামিটার সংগ্রহ দ্বারা অন্তর্ভুক্ত রয়েছে]]

কারণ
আমি আমার সঞ্চিত পদ্ধতিতে 3 টি পরামিতি দিয়ে যাচ্ছিলাম। আমি যোগ

param = command.CreateParameter();

শুধুমাত্র একবারে। প্রতিটি প্যারামিটারের জন্য আমার এই লাইনটি যুক্ত করা উচিত ছিল, এর অর্থ পুরো তিনবার।

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

সমাধান
প্রতিটি প্যারামিটারের জন্য নিম্নলিখিত কোডের লাইন যুক্ত করা হচ্ছে

param = command.CreateParameter();

0

এইভাবে আমি এটা করেছি!

        ILease lease = (ILease)_SqlParameterCollection.InitializeLifetimeService();
        if (lease.CurrentState == LeaseState.Initial)
        {
            lease.InitialLeaseTime = TimeSpan.FromMinutes(5);
            lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
            lease.RenewOnCallTime = TimeSpan.FromMinutes(2);
            lease.Renew(new TimeSpan(0, 5, 0));
        }

0

আপনি যদি এনটিটি ফ্রেমওয়ার্ক ব্যবহার করছেন

আমিও এই একই ব্যতিক্রম ছিল। আমার ক্ষেত্রে, আমি এনটিটি ফ্রেমওয়ার্ক ডিবিসিওন্টেক্সটের মাধ্যমে এসকিউএল কল করছিলাম। নিম্নলিখিতটি আমার কোড এবং কীভাবে আমি এটি ঠিক করেছি is

ব্রোকন কোড

string sql = "UserReport @userID, @startDate, @endDate";

var sqlParams = new Object[]
{
    new SqlParameter { ParameterName= "@userID", Value = p.UserID, SqlDbType = SqlDbType.Int, IsNullable = true }
    ,new SqlParameter { ParameterName= "@startDate", Value = p.StartDate, SqlDbType = SqlDbType.DateTime, IsNullable = true }
    ,new SqlParameter { ParameterName= "@endDate", Value = p.EndDate, SqlDbType = SqlDbType.DateTime, IsNullable = true }
};

IEnumerable<T> rows = ctx.Database.SqlQuery<T>(sql,parameters);

foreach(var row in rows) {
    // do something
}

// the following call to .Count() is what triggers the exception
if (rows.Count() == 0) {
    // tell user there are no rows
}

দ্রষ্টব্য: উপরের কলটি SqlQuery<T>()আসলে DbRawSqlQuery<T>বাস্তবায়িত হয় যা কার্যকর করে returnsIEnumerable

কেন কল করা। অ্যাকাউন্ট () ব্যতিক্রম ছুঁড়ে?

নিশ্চিত করার জন্য আমি এসকিউএল প্রোফাইলারকে বরখাস্ত করি নি, তবে আমার সন্দেহ হয় যে .Count()এসকিউএল সার্ভারে অন্য কলটি ট্রিগার করছে এবং অভ্যন্তরীণভাবে এটি একই SQLCommandবস্তুকে পুনরায় ব্যবহার করছে এবং সদৃশ প্যারামিটারগুলি পুনরায় যুক্ত করার চেষ্টা করছে।

সমাধান / ওয়ার্কিং কোড

আমি আমার ভিতরে একটি কাউন্টার যুক্ত করেছি foreach, যাতে আমি কল না করেই একটি সারি গণনা রাখতে পারি.Count()

int rowCount = 0;

foreach(var row in rows) {
    rowCount++
    // do something
}

if (rowCount == 0) {
    // tell user there are no rows
}

তবুও

আমার প্রকল্প সম্ভবত EF এর একটি পুরানো সংস্করণ ব্যবহার করছে। নতুন সংস্করণটি প্যারামিটারগুলি সাফ করে অথবা SqlCommandঅবজেক্টটি নিষ্পত্তি করে এই অভ্যন্তরীণ বাগটি ঠিক করেছে ।

অথবা হতে পারে, এমন স্পষ্ট নির্দেশাবলী রয়েছে যা বিকাশকারীদের .Count()একটিকে পুনরাবৃত্তি করার পরে কল না করতে বলে DbRawSqlQueryএবং আমি এটিকে ভুল কোডিং করছি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.