I am trying to create a SqlParameterCollection, but gives error while adding some SqlParameter in sp.Add() method.
Please help me how to add parameter and how to pass it to my another function where I declare a SqlConnection and SqlCommand.
SqlParameterCollection sp = null;
sp.Add(new SqlParameter("#CmpyCode", SqlDbType.NVarChar)).Value = CV.Global.CMPYCODE;
sp.Add(new SqlParameter("#Code", SqlDbType.NVarChar)).Value = codeName;
sp.Add(new SqlParameter("#DisplayCode", SqlDbType.NVarChar)).Value = codeName + "-";
sp.Add(new SqlParameter("#TotalDigit", SqlDbType.Int)).Value = CV.Global.PARAMTOTALDIGIT;
insertData("<Sp Name>", sp);
My another function is insertData(...)
internal static int insertData(string spName, SqlParameterCollection sp)
{
int retObj = 0;
using (SqlConnection con = new SqlConnection(CV.Global.CONSTRING))
{
try
{
con.Open();
SqlCommand cmd = new SqlCommand(spName, con);
cmd.CommandType = CommandType.StoredProcedure;
if (sp.Count > 0)
{
foreach (SqlParameter param in sp)
cmd.Parameters.Add(param);
}
retObj = cmd.ExecuteNonQuery();
}
catch (Exception ev)
{
Util.Log(ev);
throw;
}
finally
{
try
{
con.Close();
}
catch (Exception ev) { Util.Log(ev); throw; }
}
}
return retObj;
}
I am trying to create a SqlParameterCollection and passed it to the insertData function. But it throws an error while I am calling sp.Add() method in my first function.
The error is
Object reference not set to an instance of an object
You cannot use any variable like SqlParameterCollection (a reference object) without a call to its constructor (new), but the SqlParameterCollection is an object that cannot be initialized directly with a new. It has no public constructor and can be retrieved only from the property of an existant SqlCommand.
SqlCommand cmd = new SqlCommand(commandText, connection);
SqlParameterCollection sp = cmd.Parameters;
I suggest to change your InsertData method to accept a List<SqlParameter> and let it handle the adding of the parameters to the SqlCommand that executes the command text
List<SqlParameter> sp = new List<SqlParameter>()
{
new SqlParameter() {ParameterName = "#CmpyCode", SqlDbType = SqlDbType.NVarChar, Value= CV.Global.CMPYCODE},
new SqlParameter() {ParameterName = "#Code", SqlDbType = SqlDbType.NVarChar, Value = codeName},
new SqlParameter() {ParameterName = "#DisplayCode", SqlDbType = SqlDbType.NVarChar, Value = codeName + "-"},
new SqlParameter() {ParameterName = "#TotalDigit", SqlDbType = SqlDbType.Int, Value = CV.Global.PARAMTOTALDIGIT}
};
insertData(CV.Sps.SP_INSERT_PARAM_TABLE, sp);
and insertData simply receives an optional list of SqlParameter and add them to the internal SqlCommand parameter collection if needed
internal static int insertData(string spName, List<SqlParameter> sp = null)
{
....
if(sp != null)
cmd.Parameters.AddRange(sp.ToArray());
....
}
Here is a simplified answer. I use this type of thing for a dynamic SQL query with dynamic parameters. Sometimes you don't need all parameters if you are writing a dynamic sqlquery when determining if a variable has a value.
List<SqlParameter> paramList = new List<SqlParameter>();
paramList.Add(new SqlParameter("#StartDate", StartDate));
paramList.Add(new SqlParameter("#EndDate", EndDate));
if (TicketID != "" && TicketID != null && TicketID != "undefined")
{
paramList.Add(new SqlParameter("#TicketID", TicketID));
SQLQuery = SQLQuery + " AND A.TicketID = #TicketID";
}
var Parameters = paramList.ToArray();
List<Report> ReportList = db.Database.SqlQuery<Report>(SQLQuery, Parameters).ToList();
Related
I have created the data source within Visual Studio, I am trying to access a field called Reference No_ by using the Brief Number which is stored as No_.
argclean="AW02464";
string connectionString = "Data Source=ERP-SERVER; Initial Catalog=RMS2015; Integrated Security=True";
SqlConnection con = new SqlConnection(connectionString);
var query = "SELECT [Reference No_] FROM [RMS2015].[dbo].[RMS Live$Artwork Brief] WHERE [No_] = " + argclean + " ";
Above is my code that I have tried but I cant seem to get it to work
It's better to get in the habit of using params in your queries, such as:
var query = "SELECT [Reference No_] FROM [RMS2015].[dbo].[RMS Live$Artwork Brief] WHERE [No_] = #ArtworkNumber;
...and then:
new SqlParameter()
{
ParameterName = "#ArtworkNumber",
SqlDbType = SqlDbType.VarChar,
Value = argclean
}
UPDATE
Here is a general purpose method I use to retreive a DataTable from a query:
public static DataTable ExecuteSQLReturnDataTable(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
using (DataSet ds = new DataSet())
using (SqlConnection connStr = new SqlConnection(YourConnStr))
using (SqlCommand cmd = new SqlCommand(sql, connStr))
{
cmd.CommandType = cmdType;
cmd.CommandTimeout = EXTENDED_TIMEOUT;
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
cmd.Connection.Open();
new SqlDataAdapter(cmd).Fill(ds);
return ds.Tables[0];
}
}
It can be called like so:
DataTable dtDeliveryPerformanceResults =
SQLDBHelper.ExecuteSQLReturnDataTable(
PLATYPUS_STOREDPROC,
CommandType.StoredProcedure,
new SqlParameter()
{
ParameterName = "#Unit",
SqlDbType = SqlDbType.VarChar,
Value = unit
},
new SqlParameter()
{
ParameterName = "#BeginDate",
SqlDbType = SqlDbType.DateTime,
Value = _begDate
},
new SqlParameter()
{
ParameterName = "#EndDate",
SqlDbType = SqlDbType.DateTime,
Value = _endDate
},
new SqlParameter()
{
ParameterName = "#PoisonToeLength",
SqlDbType = Convert.ToInt32(SqlDbType.Int),
Value = 42
}
);
The example shows calling a Stored Procedure (a recommended practice), but you can use it with "regular" or "plain vanilla" SQL queries, too.
Thanks to some tips and reminders here, I changed my code from this kludgy mess:
try
{
DataSet dsUsage = new DataSet();
SqlConnection conn = new SqlConnection("SERVER=PROSQL05;DATABASE=platypusdata;UID=duckbill;PWD=poisonToe42;Connection Timeout=0");
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = String.Format("Exec sp_ViewProductUsage_MappingRS '{0}', '{1}', '{2}'", mammal, dateBegin, dateEnd);
da.SelectCommand = cmd;
conn.Open();
da.Fill(dsUsage);
conn.Close();
DataTable dtUsage = dsUsage.Tables[0];
if (dtUsage.Rows.Count > 0)
{
foreach (DataRow productUsageByMonthDataRow in dtUsage.Rows)
{
. . .
...to this:
try
{
SqlDataAdapter da = new SqlDataAdapter();
DataSet dsUsage = new DataSet();
using (SqlConnection conn = new SqlConnection(UsageRptConstsAndUtils.PlatypusConnStr))
{
using (SqlCommand cmd = new SqlCommand("sp_ViewProductUsage_MappingRS", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#Unit", SqlDbType.VarChar).Value = _unit;
cmd.Parameters.Add("#BegDate", SqlDbType.DateTime).Value = dtBegin;
cmd.Parameters.Add("#EndDate", SqlDbType.DateTime).Value = dtEnd;
da.SelectCommand = cmd;
conn.Open();
//cmd.ExecuteReader(); <- Is this even necessary?
da.Fill(dsUsage);
}
}
DataTable dtUsage = dsUsage.Tables[0];
if (dtUsage.Rows.Count > 0)
{
// Populate the cells
foreach (DataRow productUsageByMonthDataRow in dtUsage.Rows)
{
. . .
Note that I have SqlCommand's ExecuteReader commented out in the new code because it seems unnecessary due to the SqlDataAdapter being provided the SqlCommand. It works fine. So: am I correct in assuming I can remove cmd.ExecuteReader() altogether? Is there any benefit in retaining it, or would that be totally redundant and create "busy work" for the process?
UPDATE
So, to pass an array of SqlParameter (to the ExecuteDataSet method in MethodMan's answer), I take it that I would first have to do something like:
SqlParameter sqlp = new SqlParameter();
sqlp.ParameterName = "Unit";
sqlp.Value = _unit;
cmd.Parameters.Add(sqlp);
...etc. (and then add them to an array - or, possibly better a generic list of SqlParameter).
UPDATE 2
I just ran into this for the first time: if you use MethodMan's example (which I do) and you use a parameterless query, you need to bypass the parameter-adding loop like so:
if (null != parameters)
{
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
}
I would personally create a SqlDBHelper class and pass call the stored procedure using a method such as this
public static class SqlDBHelper
{
public static DataSet ExecuteDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
using (DataSet ds = new DataSet())
using (SqlConnection connStr = new SqlConnection(ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, connStr))
{
cmd.CommandType = cmdType;
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
try
{
cmd.Connection.Open();
new SqlDataAdapter(cmd).Fill(ds);
}
catch (SqlException ex)
{
//log to a file or write to Console for example
Console.WriteLine(ex.Message);
}
return ds;
}
}
}
If you want to return a DataTable then change the return type in the Method signature and call the following in the return statement below
public static DataTable ExecuteDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
return ds.Tables[0];
Here is an example on how you would call the method
someDataTable = SqlDBHelper.ExecuteDataSet("sp_ViewProductUsage_MappingRS", CommandType.StoredProcedure,
new SqlParameter() { ParameterName = "#Unit", SqlDbType = SqlDbType.VarChar, Value = _unit },
new SqlParameter() { ParameterName = "#BegDate", SqlDbType = SqlDbType.DateTime, Value = dtBegin },
new SqlParameter() { ParameterName = "#EndDate", SqlDbType = SqlDbType.DateTime, Value = dtEnd }
);
The code in c#:
public List<Per> RunSpForAotuComplete(string storedProcName, string text)
{
OleDbDataReader rdr =null;
List<Per> dictionary = new List<Per>();
OleDbConnection connection = new OleDbConnection(ConString);
connection.Open();
OleDbCommand cmd = new OleDbCommand(storedProcName, connection)
{
CommandType = CommandType.StoredProcedure
};
OleDbParameter parameter = new OleDbParameter("#text", text);
cmd.Parameters.Add(parameter);
rdr = cmd.ExecuteReader();
if (rdr.HasRows)
{
while (rdr.Read())
{
dictionary.Add(new Per
{
name = rdr["semel"].ToString(),
value = rdr["shem"].ToString(),
});
}
}
}
I do not understand why if(rdr.HasRows)=false?
This procedure is written:
SELECT shem, semel
FROM TYISHUV
WHERE shem like #text +'*';
I also tried to do:
OleDbParameter parameter = new OleDbParameter("text", text);
Instead of:
OleDbParameter parameter = new OleDbParameter("#text", text);
update your procedure as
SELECT shem, semel
FROM TYISHUV
WHERE shem like ?;
when you add parameter,
text = text+'*';
cmd.Parameters.AddWithValue("#text", text);
Towards the end of my code I am calling a stored procedure which updates a table based on the parameters passed by my page. I get the following error:
Procedure or function 'Res_invpush_UpdateInv' expects parameter '#InventoryPushSubscriptionId', which was not supplied.
Even thought my parameter value is being successfully passed - I know this because I have tested using breakpoints and when I mouse over on the parameter mentioned it gives the value of 1 so I don't know why the message is still coming.
Can somebody please show me where exactly am I going wrong or how to fix it?
SendInvUpdate.InvServices.UpdateRatePackagesRequest ur = new SendInvUpdate.InvServices.UpdateRatePackagesRequest();
SendInvUpdate.InvServices.UpdateRatePackagesOperationResponse or = new SendInvUpdate.InvServices.UpdateRatePackagesOperationResponse();
protected void Page_Load(object sender, EventArgs e)
{
try
{
string connStr = ConfigurationManager.ConnectionStrings["bb"].ConnectionString;
SqlConnection Con = new SqlConnection(connStr);
Con.Open();
SqlCommand cmd = new SqlCommand("invpush_PollForAvailableChanges", Con);
cmd.CommandType = CommandType.StoredProcedure;
SqlParameter NewSysChangeVersionParam = new SqlParameter("#NewSysChangeVersion", SqlDbType.Int);
NewSysChangeVersionParam.Value = (object)NewSysChangeVersionParam ?? DBNull.Value;
NewSysChangeVersionParam.Direction = ParameterDirection.InputOutput;
NewSysChangeVersionParam.SqlDbType = SqlDbType.BigInt;
SqlDataReader sdr = cmd.ExecuteReader();
InventoryPushSubscriptionRecord rec = new InventoryPushSubscriptionRecord();
while (sdr.Read())
{
rec.InventoryPushSubId = sdr.GetInt32(0);
rec.CMName = sdr.GetString(1);
rec.NotifUrl = sdr.GetString(2);
rec.Options = sdr.GetString(3);
rec.LastSysChangeVersion = sdr.IsDBNull(4)?(long?)null:sdr.GetInt32(4);
}
if(!sdr.NextResult()) throw new System.Exception("Expected Result set 1 for InventoryChangeRecord");
InventoryChangeRecord inrec = new InventoryChangeRecord();
while (sdr.Read())
{
inrec.InventoryPushSubId= sdr.GetInt32(0);
inrec.SysChangeVersion=sdr.IsDBNull(1)?(long?)null:sdr.GetInt32(1);
inrec.InvDate=sdr.GetDateTime(2);
inrec.ResId=sdr.GetInt32(3);
inrec.RoomType=sdr.GetString(4);
inrec.InvCount=sdr.GetInt32(5);
inrec.ResName=sdr.GetString(6);
}
sdr.Close();
sdr.Dispose();
if (NewSysChangeVersionParam != null)
{
SendInvUpdate.InvServices.InventoryServiceClient isc = new SendInvUpdate.InvServices.InventoryServiceClient();
or = isc.UpdateRatePackages(request);
res = or.Results.ToString();
int Subid;
SubId=inrec.InventoryPushSubscriptionId;
SqlCommand ucmd = new SqlCommand("Res_invpush_UpdateInv", Con);
ucmd.CommandType = CommandType.StoredProcedure;
SqlParameter LastChange = new SqlParameter("#NewLastSysChangeVersion", SqlDbType.Int);
LastChange.Value = NewSysChangeVersionParam;
SqlParameter SubscriptionId = new SqlParameter("InventoryPushSubscriptionId", SqlDbType.Int);
SubscriptionId.Value = SubId;
ucmd.ExecuteNonQuery();
}
}
}
}
catch (Exception ex)
{
throw (ex);
}
}
}
First, as Mike mentions, you should be consistent with the parameter naming.
e.g.
SqlParameter SubscriptionId = new SqlParameter("InventoryPushSubscriptionId", SqlDbType.Int);
should be
SqlParameter SubscriptionId = new SqlParameter("#InventoryPushSubscriptionId", SqlDbType.Int);
And then as #NSGaga points out, you are not really passing the parameters to the command, you just create the objects and aren't using them anywhere.
Like this:
SqlParameter LastChange = new SqlParameter("#NewLastSysChangeVersion", SqlDbType.Int);
LastChange.Value = NewSysChangeVersionParam;
ucmd.Parameters.Add(LastChange);
SubscriptionId = new SqlParameter("#InventoryPushSubscriptionId", SqlDbType.Int);
SubscriptionId.Value = SubId;
ucmd.Parameters.Add(SubscriptionId);
Hope this helps
You are not setting the parameters property for command object, your code is,
SqlCommand ucmd = new SqlCommand("Res_invpush_UpdateInv", Con);
ucmd.CommandType = CommandType.StoredProcedure;
SqlParameter LastChange = new SqlParameter("#NewLastSysChangeVersion", SqlDbType.Int);
LastChange.Value = NewSysChangeVersionParam;
SqlParameter SubscriptionId = new SqlParameter("InventoryPushSubscriptionId", SqlDbType.Int);
You can see that parameter are not assigned to command object's parameter property and hence stored procedure is not getting parameters. Just add the following before ExecuteNonQuery statement,
command.Parameters.Add(LastChange);
command.Parameters.Add(SubscriptionId );
The error is cannot convert object to sql parameter
I'm working with a bol->dal, building an array of parameters to pass to the dal:
bol:
SqlParameter[] sqlParams = new SqlParameter[]
{
new SqlParameter("#p1", SqlDbType.VarChar, 30).Value = "val1",
new SqlParameter("#p2", SqlDbType.VarChar, 30).Value = "val2"
};
dal:
public static int ExecuteNonQuery(string sql, SqlParameter[] #params)
{
SqlConnection cnn = new SqlConnection(connectionstring);
SqlCommand cmd = new SqlCommand(sql, cnn);
for (int i = 0; i <= #params.Length - 1; i++)
{
cmd.Parameters.Add(#params[i]);
}
foreach (IDataParameter param in cmd.Parameters)
{
if (param.Value == null) param.Value = DBNull.Value;
}
cnn.Open();
int retval = cmd.ExecuteNonQuery();
cnn.Close();
return retval;
}
I need help improving this, thanks--
You need to pass in the actual SqlParameter. Notice the object initializer of the Value:
var sqlParams = new SqlParameter[]
{
new SqlParameter("#p1", SqlDbType.VarChar, 30) {Value = "val1"},
new SqlParameter("#p2", SqlDbType.VarChar, 30) {Value = "val2"},
};