Understanding 'The SqlParameter is already contained by another SqlParameterCollection' - c#

I have the following piece of code:
SqlParameter invidParam = new SqlParameter("#invid",obj.INVID);
SqlParameter prodParam = new SqlParameter("#prod", obj.PROD);
SqlParameter descrParam = new SqlParameter("#descr", obj.DESCR);
SqlParameter qtyParam = new SqlParameter("#qty", 1);
if(SessionHelper.TryGetSession("curUser",out User user))
{
SqlParameter useridParamCheck = new SqlParameter("#userid", user.Username);
var queryResult = db.Database.SqlQuery<int>("EXEC CheckIfAlreadyInPR#invid#userid #invid, #userid", invidParam, useridParamCheck);
var qty = queryResult.FirstOrDefault();
if (qty == 0)
{
SqlParameter useridParamInsert = new SqlParameter("#userid", user.Username);
var insertResult = db.Database.ExecuteSqlCommand("InsertIntoPR #invid, #prod, #descr, #userid, #qty", invidParam, prodParam, descrParam, useridParamInsert, qtyParam);
}
else if (qty > 0)
{
SqlParameter qtyParameter = new SqlParameter("#newqty", (qty + 1));
SqlParameter userIdParamUpdate = new SqlParameter("#userid", user.Username);
var updateResult = db.Database.ExecuteSqlCommand("UpdatePRQty#invid#userid#newqty #invid,#userid,#newqty",invidParam,userIdParamUpdate,qtyParameter);
}
}
My program runs and hits an exception at the line var insertResult = db...
I am trying to understand which SqlParameter is already contained in another collection. Is it because the parameter #userid is already used in the previous stored procedure call ?
I declared the SqlParameter("#userid") 3 times, with different variable names:
useridParamCheck, useridParamInsert, userIdParamUpdate
Did this cause the error because the name #userid is used? If I use #userid1, #userid2, #userid3 will the problem be resolved? Or the SqlParameter that is already contained is some other SQL parameters that I declared above?
Thank you

I'm going to suggest that invidparam is your problem parameter as it is the only parameter I can see that is used twice. Once in db.Database.SqlQuery<int>("EXEC CheckIfAlreadyInPR#invid#userid #invid, #userid", invidParam, useridParamCheck); and again in both instances of db.Database.ExecuteCommand().
The error itself relates to an SqlParameter object being used multiple times rather than the same parameter name being used multiple times.

I was getting this error with the following code
var p = new System.Data.SqlClient.SqlParameter{ParameterName = "#p0", SqlDbType
SqlDbType.DateTime ,Value = ut.ReadyByDate, };
var nextTasksResults = db.Database.SqlQuery<nextTask>(sql2, p);
var isAny = nextTaskResults.Any() // error
The work around was to send to an array and use that
var nextTasks = nextTasksResults.ToArray();
var isAny = nextTasks.Any();

Related

Insert with a stored procedure and return an output parameter

I am trying to insert values in an Entity database and return true if everything is OK. I tested my stored procedure and it is working fine but when I try to call it from the code I am getting the following error:
No mapping exists from object type System.Collections.Generic.List`1
My question is: am I calling it properly?
using (Entities ent = new Entities())
{
List<SqlParameter> parameters = new List<SqlParameter>();
parameters.Add(new SqlParameter("#Parameter1", "Parameter1"));
parameters.Add(new SqlParameter("#Parameter2", "Parameter2"));
SqlParameter outputParameter = new SqlParameter();
outputParameter.ParameterName = "#Confirm";
outputParameter.SqlDbType = System.Data.SqlDbType.Bit;
outputParameter.Direction = System.Data.ParameterDirection.Output;
parameters.Add(new SqlParameter("#Confirm", outputParameter));
ent.Database.ExecuteSqlCommand("exec TestProc #Parameter1, #Parameter2", parameters);
bool success = Convert.ToBoolean(outputParameter.Value);
}
ExecuteSqlCommand takes an object[] not a List, so pass parameters.ToArray().
Also don't indicate success or failure with an output parameter. Just throw an error from the stored procedure if something goes wrong.
And change
SqlParameter outputParameter = new SqlParameter();
outputParameter.ParameterName = "#Confirm";
outputParameter.SqlDbType = System.Data.SqlDbType.Bit;
outputParameter.Direction = System.Data.ParameterDirection.Output;
parameters.Add(new SqlParameter("#Confirm", outputParameter));
to
SqlParameter outputParameter = new SqlParameter();
outputParameter.ParameterName = "#Confirm";
outputParameter.SqlDbType = System.Data.SqlDbType.Bit;
outputParameter.Direction = System.Data.ParameterDirection.Output;
parameters.Add( outputParameter );

Pass Array as parameter to Oracle stored proc from c# to bulk insert

I am trying to send arrays as parameter to Oracle stored proc in order to process bulk insert.
type Licensingentity_id is table of odilic_admin.licensingentity.licensingentity_id%type index by pls_integer;
type Nationalprovidernumber is table of odilic_admin.licensingentity.nationalprovidernumber%type index by pls_integer;
type Home_state_province_id is table of odilic_admin.licensingentity.home_state_province_id%type index by pls_integer;
procedure HomeStateLookup_bulk_insert(i_entityId in Licensingentity_id,
i_npn in Nationalprovidernumber,
i_homeStateId in Home_state_province_id) is
v_caller varchar2(60) := 'System_Scheduler';
begin
FORALL i IN 1 .. i_entityId.count
insert into home_state_lookup_stg
(licensingentity_id,
npn,
home_state_province_id,
isprocessed,
inserted_by,
inserted_date,
updated_by,
updated_date)
values
(i_entityId(i),
i_npn(i),
i_homeStateId(i),
0,
v_caller,
sysdate,
v_caller,
sysdate);
end HomeStateLookup_bulk_insert;
and here is the c# code
NiprConnectionString = ConfigurationManager.ConnectionStrings["ODI.NIPR.DB.Reader"].ConnectionString;
OracleConnection cnn = new OracleConnection(NiprConnectionString);
cnn.Open();
OracleCommand cmd = cnn.CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = NaicStateLookupRepositoryProcedures.HOME_STATE_BULK_INSERT;
cmd.BindByName = true;
cmd.ArrayBindCount = entities.Count;
var i_entityId = new OracleParameter();
var i_npn = new OracleParameter();
var i_homeStateId = new OracleParameter();
i_entityId.OracleDbType = OracleDbType.Int32;
i_npn.OracleDbType = OracleDbType.Varchar2;
i_homeStateId.OracleDbType = OracleDbType.Int32;
i_entityId.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
i_npn.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
i_homeStateId.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
i_entityId.Value = entities.Select(c => c.Key).ToArray();
i_npn.Value = entities.Select(c => c.Value.Item1).ToArray();
i_homeStateId.Value = entities.Select(c => c.Value.Item2).ToArray();
i_entityId.Size = entities.Count;
i_npn.Size = entities.Count;
i_homeStateId.Size = entities.Count;
cmd.Parameters.Add(i_entityId);
//cmd.Parameters[0].Value = i_entityId;
cmd.Parameters.Add(i_npn);
//cmd.Parameters[1].Value = i_npn;
cmd.Parameters.Add(i_homeStateId);
//cmd.Parameters[2].Value = i_homeStateId;
int result = cmd.ExecuteNonQuery();
but getting an exception -
ORA-06550: line 1, column 52: PLS-00103: Encountered the symbol ">"
when expecting one of the following:
( ) - + case mod new not null
Any help is much appreciated.
I can't promise this is the answer, and I don't have the tables you reference to test this for myself, but at first glance I noticed you set:
cmd.BindByName = true;
As such, I think you need to declare your parameter names:
var i_entityId = new OracleParameter("i_entityId");
var i_npn = new OracleParameter("i_npn");
var i_homeStateId = new OracleParameter("i_homeStateId");
I've never passed an array as a parameter to a procedure, but if you were to do this with a normal insert, it would look something like this:
string sql = "insert into foo values (:boo, :bar, :baz)";
OracleCommand cmd = new OracleCommand(sql, conn);
cmd.Parameters.Add(new OracleParameter("boo", OracleDbType.Varchar2));
cmd.Parameters.Add(new OracleParameter("bar", OracleDbType.Date));
cmd.Parameters.Add(new OracleParameter("baz", OracleDbType.Varchar2));
cmd.Parameters[0].Value = booArray;
cmd.Parameters[1].Value = barArray;
cmd.Parameters[2].Value = bazArray;
cmd.ArrayBindCount = booArray.Length;
cmd.ExecuteNonQuery();
I would start by defining the parameters with the parameter names, though.

How to get the output parameter value from a stored procedure that already returns a data set?

I am using a stored procedure in ASP.NET MVC to return a data set AND several output parameters. I have the data set working great, and I am able to manipulate the data set into a organized table. The problem is with my output parameters. I have the direction set to output, and I have them seemingly correct. How can I get the value of these few output parameters without jeopardizing my data set?
Controller Action:
[HttpPost]
public ActionResult Search(SqlViewModel sT)
{
var rMaxBalPoint = new SqlParameter("#MaxBalPoint", SqlDbType.Decimal);
rMaxBalPoint.Direction = System.Data.ParameterDirection.Output;
var rMinBalPoint = new SqlParameter("#MinBalPoint", SqlDbType.Decimal);
rMinBalPoint.Direction = System.Data.ParameterDirection.Output;
var rIntBalPoint = new SqlParameter("#IntBalPoint", SqlDbType.Decimal);
rIntBalPoint.Direction = System.Data.ParameterDirection.Output;
var rMaxEER = new SqlParameter("#MaxEER", SqlDbType.Decimal);
rMaxEER.Direction = System.Data.ParameterDirection.Output;
var rMinEER = new SqlParameter("#MinEER", SqlDbType.Decimal);
rMinEER.Direction = System.Data.ParameterDirection.Output;
var rIntEER = new SqlParameter("#IntEER", SqlDbType.Decimal);
rIntEER.Direction = System.Data.ParameterDirection.Output;
var rCooling = new SqlParameter("#Cooling", SqlDbType.Decimal);
rCooling.Direction = System.Data.ParameterDirection.Output;
var rEnergy = new SqlParameter("#Energy", SqlDbType.Decimal);
rEnergy.Direction = System.Data.ParameterDirection.Output;
var rSql = new SqlParameter("#Sql", SqlDbType.Decimal);
rSql.Direction = System.Data.ParameterDirection.Output;
var sql = db.Database.SqlQuery<Get_Sql_Result>("Get_Sql #Type, #Q_HA, #Q_HB, #Q_LF, #Q_LB, #ESS_HA, #ESS_HB, #ESS_LF, #ESS_LB, #CD, #MaxBalPoint, #MinBalPoint, #IntBalPoint, #MaxEER, #MinEER, #IntEER, #Cooling, #Energy, #Sql, #CDHS, #Q_I, #ESS_I",
new SqlParameter("#Type", sT.type),
new SqlParameter("#Q_HA", sT.Q_HA),
new SqlParameter("#Q_HB", sT.Q_HB),
new SqlParameter("#Q_LF", sT.Q_LF),
new SqlParameter("#Q_LB", sT.Q_LB),
new SqlParameter("#ESS_HA", sT.ESS_HA),
new SqlParameter("#ESS_HB", sT.ESS_HB),
new SqlParameter("#ESS_LF", sT.ESS_LF),
new SqlParameter("#ESS_LB", sT.ESS_LB),
new SqlParameter("#CD", sT.cd),
rMaxBalPoint,
rMinBalPoint,
rIntBalPoint,
rMaxEER,
rMinEER,
rIntEER,
rCooling,
rEnergy,
rSql,
new SqlParameter("#CDHS", sT.cdhs),
new SqlParameter("#Q_I", sT.Q_I),
new SqlParameter("#ESS_I", sT.ESS_I));
SqlPartialViewModel obj = new SqlPartialViewModel();
obj.SqlData = sql;
return View("Example",obj);
The parameter collection will contain the output values of your parameters.
I think you're getting stuck here because the parameter collection isn't persisted anywhere; you're just declaring an ad-hoc collection. If you predeclare your parameters collection, you should be able to get the values out of it perfectly happily.

Pervasive SQL System Stored Procedure from ADO.NET error

I'm just trying to return a list of columns and their attributes through a system stored procedure. What documentation I have seems to say the below code should work, but I get "Pervasive.Data.SqlClient.Lna.k: [LNA][Pervasive][ODBC Engine Interface]Invalid or missing argument." on the execute. This is PSQL v11, .NET 4.5.
using (PsqlConnection conn = new PsqlConnection(cs))
{
PsqlCommand locationCmd = new PsqlCommand();
PsqlParameter tableParam = new PsqlParameter();
PsqlParameter returnParam = new PsqlParameter();
returnParam.Direction = ParameterDirection.ReturnValue;
locationCmd.CommandText = "psp_columns";
locationCmd.Connection = conn;
locationCmd.CommandType = CommandType.StoredProcedure;
locationCmd.Parameters.Add(tableParam).Value = table;
locationCmd.Parameters.Add(returnParam);
conn.Open();
locationCmd.ExecuteNonQuery();
}
I would think the problem is this line:
locationCmd.Parameters.Add(tableParam).Value = table;
You should set the value before adding the parameter, not afterwards.
tableParam.Value = table;
locationCmd.Parameters.Add(tableParam);
I don't know about Psql but for MSSQL normally you also need to define the parameter name as its found in the stored procedure, or at least that's what I do.
SqlParameter param = new SqlParameter("#tableParam", value);
The psp_Columns system stored procedure is defined as call psp_columns(['database_qualifier'],'table_name', ['column_name']). I know that it says the database qualifier is optional, but I think it's required. You could try passing an empty string for the qualifier. Something like:
using (PsqlConnection conn = new PsqlConnection(cs))
{
PsqlCommand locationCmd = new PsqlCommand();
PsqlParameter dbParam = new PsqlParameter();
PsqlParameter tableParam = new PsqlParameter();
PsqlParameter returnParam = new PsqlParameter();
returnParam.Direction = ParameterDirection.ReturnValue;
locationCmd.CommandText = "psp_columns";
locationCmd.Connection = conn;
locationCmd.CommandType = CommandType.StoredProcedure;
locationCmd.Parameters.Add(dbParam).Value = ""; //might need two single quotes ('')
locationCmd.Parameters.Add(tableParam).Value = table;
locationCmd.Parameters.Add(returnParam);
conn.Open();
locationCmd.ExecuteNonQuery();
}
You should try to get the information of the table SCHEMA using the provided GetSchema method from the Psqlconnection. I have searched a bit on their support site and it seems that this method is supported although I haven't find a direct example using the Tables collection.
This is just an example adapted from a test on mine on SqlServer, I don't have Pervasive install, but you could try if the results are the same
using(PsqlConnection cn = new PsqlConnection("your connection string here"))
{
cn.Open();
string[] selection = new string[] { null, null, table };
DataTable tbl = cn.GetSchema("Columns", selection);
foreach (DataRow row in tbl.Rows)
{
Console.WriteLine(row["COLUMN_NAME"].ToString() + " " +
row["IS_NULLABLE"].ToString() + " " +
row["DATA_TYPE"].ToString()
);
}
}
i was trying to figure this out as well, but with the tables procedure. even though the database and table names are optional, you still have to provide values. for optional parameters, pass in DBNull.Value
this worked for me:
PsqlCommand cm = new PsqlCommand();
cm.CommandText = "psp_tables";
cm.CommandType = CommandType.StoredProcedure;
cm.Connection = new PsqlConnection();
cm.Connection.ConnectionString = <your connection string>;
cm.Parameters.Add(":database_qualifier", DBNull.Value);
cm.Parameters.Add(":table_name", DBNull.Value);
cm.Parameters.Add(":table_type", "User table");

Can't get it! SqlParameter with ParameterName is not contained by this SqlParameterCollection. Stored proc param

I know that this question has been asked many times, And I have read many many answers, yet I can't figure out what is wrong. It's been hours. Any help would be soo appreciated. I am just trying to call a stored procedure in an ASP page, and I am unable to add the parameter properly, getting the exception that it is not in the collection.
I have modified my proc as follows to try to make it simple and isolate the issue.
ALTER PROCEDURE [dbo].[up_validateUserWithClinicCount]
#HTID INT = 0,
#ValidUserID INT OUTPUT,
#MultiClinicFlag INT OUTPUT
AS
DECLARE #vClinicCount INT = null
DECLARE #vUserValid INT = null
BEGIN
SET #ValidUserID = 2
SET #MultiClinicFlag = 1
END;
AND the C# code
String connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["PC3PaymentConnection"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand("up_validateUserWithClinicCount", connection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#HTID", htId);
SqlParameter uidOut = new SqlParameter("#ValidUserID", SqlDbType.Int);
uidOut.Size = 4;
uidOut.Direction = ParameterDirection.Output;
cmd.Parameters.Add(uidOut);
SqlParameter pMultiClinics = new SqlParameter();
pMultiClinics.ParameterName = "#MultiClinicFlag";
pMultiClinics.SqlDbType = SqlDbType.Int;
pMultiClinics.Direction = ParameterDirection.Output;
cmd.Parameters.Add(pMultiClinics);
try
{
cmd.ExecuteNonQuery();
//--> Error points to the next line, and I have tried to use int.parse rather than convert also, with the same error -- parameter not in collection
MultiClinics = Convert.ToInt16(cmd.Parameters["pMultiClinics"].Value);
PC3User = Convert.ToInt16(uidOut.Value.ToString());
}
catch (SqlException sqlEx)
{
LbMsg.ForeColor = System.Drawing.Color.Red;
LbMsg.Text = sqlEx.Message;
}
}
}
Thanks if you can see what I am missing.
You have an object reference for the parameter already, you don't need to grab it from the parameters collection. Also, sql ints are 32-bit.
MultiClinics = (int)pMultiClinics.Value;
To retrieve from the parameter collection, use the ParameterName you gave it:
MultiClinics = (int)cmd.Parameters["#MultiClinicFlag"].Value;

Categories