Getting a bit value from stored procedure in C# - c#

The situation is following, i have a stored procedure in SQL Server , this has a few output parameters, one of them is a bit type, what I want is to take the value of that parameter, but I have a conversion error, InvalidCastException.
This is my code:
public void exec()
{
String strConnString = "Server=.\\SQLEXPRESS;Database=recalls;Integrated Security=true";
SqlConnection con = new SqlConnection(strConnString);
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "findVinCamp";
int c = Int32.Parse(campaing.Text);
cmd.Parameters.Add("#camp", SqlDbType.Int).Value = c;
cmd.Parameters.Add("#vin", SqlDbType.VarChar, 100).Value = vin.Text;
cmd.Parameters.Add("#desc", SqlDbType.NVarChar, 255).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#st", SqlDbType.VarChar, 50).Direction = ParameterDirection.Output;
cmd.Parameters.Add("#bit", SqlDbType.Bit).Direction = ParameterDirection.Output;
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
bit = (int)cmd.Parameters["#bit"].Value; //Exception Here
if (bit == 1)
{
desc.Text = cmd.Parameters["#desc"].Value.ToString();
stt.Text = cmd.Parameters["#st"].Value.ToString();
camp = cmd.Parameters["#camp"].Value.ToString();
if (stt.Text.Equals("APPLIED"))
{
stt.ForeColor = System.Drawing.Color.LawnGreen;
}
else
{
stt.ForeColor = System.Drawing.Color.Firebrick;
label3.Enabled = true;
newstatus.Enabled = true;
update.Enabled = true;
}
}
else
{
MessageBox.Show("Doesn't exits!");
}
}
I'm trying to assign the bit parameter to a int variable. Any question post on comments.

I change the (int) to this, now works perfectly:
Boolean lol = Convert.ToBoolean(cmd.Parameters["#bit"].Value);

Use this following Line
bool isConfirmed = (bool)cmd.Parameters["#bit"].Value;
if(isConfirmed ){
desc.Text = cmd.Parameters["#desc"].Value.ToString();
stt.Text = cmd.Parameters["#st"].Value.ToString();
camp = cmd.Parameters["#camp"].Value.ToString();
if (stt.Text.Equals("APPLIED"))
{
stt.ForeColor = System.Drawing.Color.LawnGreen;
}
else
{
stt.ForeColor = System.Drawing.Color.Firebrick;
label3.Enabled = true;
newstatus.Enabled = true;
update.Enabled = true;
}
}
else{
MessageBox.Show("Doesn't exits!");
}
**UPDATE: **if the bit column allows nulls -- many ways you can do this
bool isConfirmed = cmd.Parameters["#bit"].Value as bool? ?? null;
and also read this- SQL Server Data Types and Their .NET Framework Equivalents

I believe a bit will convert to a boolean. Which should make your code a bit simpler too.
i.e.
...
var bit = (bool)cmd.Parameters["#bit"].Value;
if (bit)
{
...

You are trying to convert your boolean output to INT, please convert it in Boolean:
bool bitValue= Convert.ToBoolean(cmd.Parameters["#bit"].Value)

Related

How can I allow a SqlParameter to accept any value in SqlClient?

I'm trying to create a generic function, using SqlClient in C#, which will accept a value for any column name and return the valid objects. My approach is to create a stored procedure which accepts values for every column, and where a value has not been provided it will be assume that any value is accepted. My code is as below (code is a little unfinished with regards the final requirement):
public async Task<List<OrganisationInstance>> GetOrganisationInstances(string name, int id)
{
List<OrganisationInstance> responses = new List<OrganisationInstance>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand(OrganisationInstancesSP.READ_ORGANISATION, connection))
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("Id", SqlDbType.BigInt).Value = 2;
command.Parameters.Add("CreationDate", SqlDbType.DateTime).Value = "2021-12-14 23:59:25.837";
command.Parameters.Add("CompanyName", SqlDbType.VarChar).Value = "xxxxxxxxxx";
command.Parameters.Add("Postcode", SqlDbType.VarChar).Value = "xxxxxxxxxxx";
command.Parameters.Add("FormationDate", SqlDbType.DateTime).Value = "2021-12-14 23:59:25.837";
command.Parameters.Add("NodeId", SqlDbType.Int).Value = id;
SqlDataReader reader = await command.ExecuteReaderAsync();
while (reader.Read())
responses.Add(new OrganisationInstance { CompanyName = reader["CompanyName"].ToString(), Id = Convert.ToInt32(reader["Id"]) });
}
}
catch (DbException ex)
{
return null;
}
finally
{
connection.Close();
}
}
return responses;
}
The query returns the expected object, when all values are set to the values of an instance/row in the database. However, I cannot find a way to set the column to allow any value.
In SQL, it would be possible to say WHERE CreationDate = CreationDate , which would translate to:
command.Parameters.Add("CreationDate", SqlDbType.DateTime).Value = "CreationDate";
However, this doesn't work in SqlClient. Can anyone suggest how I might achieve this?

C# ExecuteReader has rows but result view initially with question marks

ExecuteReader has rows but initially when i hover and look at result view it has question marks for all the rows. Then when i go back in a second time to hover it says enumeration yielded no results. the HasRows is true however. I'm also getting my output parameters fine, but not the result set from the select statement. I'm executing a sql server stored proc. the SP executes fine in management studio. And again i am getting the output parms, just not the result set.
internal static CrossWalk Create(string senderId, string ediType)
{
var connection = ConfigurationManager.ConnectionStrings["caeCustom"];
DbCommand cmd = new SqlCommand();
cmd.CommandText = "emb_edi_xwalk_select";
cmd.CommandType = CommandType.StoredProcedure;
cmd.AddParameter("#pSENDER_ID", senderId);
cmd.AddParameter("#pMAPPING_TYPE", ediType);
var delegateId = new SqlParameter
{
ParameterName = "#pDELEGATE_ID",
SqlDbType = SqlDbType.Int,
Direction = ParameterDirection.Output
};
cmd.Parameters.Add(delegateId);
var crossWalk = new CrossWalk();
var dbFactory = DbProviderFactories.GetFactory(connection.ProviderName);
using(var sqlConnection =
dbFactory.CreateConnection(connection.ConnectionString))
{
cmd.Connection = sqlConnection;
using (var sqlReader = cmd.ExecuteReader())
{
if (sqlReader.HasRows)
{
while (sqlReader.Read())
{
//Mapping of AAA values will be AAA03~internal_value -->
loop~external_value
//i.e. AAA03~1008 --> 2010EA~51
string key;
string value;
if (sqlReader["element"].ToString() == "AAA03")
{
key = string.Join("~",
sqlReader["element"].ToString(), sqlReader["internal_value"].ToString());
value = string.Join("~", sqlReader["loop"].ToString(),
sqlReader["external_value"].ToString());
}
else
//Normal xwalk mapping will be loop+element~external_value
--> internal_value
//i.e. 2010ANM101~X3 --> 3
{
key = string.Join("~", sqlReader["loop"] +
sqlReader["element"].ToString(), sqlReader["external_value"].ToString());
value = sqlReader["internal_value"].ToString();
}
crossWalk._lookups.Add(key, value);
}
}
sqlReader.Close();
}
crossWalk.DelegateId =
Convert.ToInt32(cmd.Parameters["#pDELEGATE_ID"].Value);
}
return crossWalk;
}

How can i check what is variable into the SqlDataReader?

I'm new to C#, and write this code for calling a SQL Server stored procedure:
using (SqlConnection con = new SqlConnection(Connection))
{
using (SqlCommand cmd = new SqlCommand("CheckValidbehzad", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#p_bank", SqlDbType.VarChar).Value = p_bank;
cmd.Parameters.Add("#p_pay_date", SqlDbType.VarChar).Value = p_pay_date;
cmd.Parameters.Add("#p_bill_id", SqlDbType.VarChar).Value = p_bill_id;
cmd.Parameters.Add("#p_payment_id", SqlDbType.VarChar).Value = p_payment;
cmd.Parameters.Add("#p_ref_code", SqlDbType.VarChar).Value = p_ref_code;
cmd.Parameters.Add("#p_branch", SqlDbType.VarChar).Value = p_branch;
cmd.Parameters.Add("#p_channel_type", SqlDbType.VarChar).Value = p_channel;
cmd.Parameters.Add("#p_send_date", SqlDbType.VarChar).Value = p_send_date;
con.Open();
reader = cmd.ExecuteReader();
while (reader.Read())
{
//TempCode = reader["PaymentID"].ToString();
}
}
}
That stored procedure sometimes return ErrorNumber in result and sometimes it returns PaymentID. How can I check this scenario?
if( reader has ErrorNumber field) then
do something
else
do something else
Thanks all.
Not sure how exactly you can distinguish these two columns returned - if the column is present or missing (depending on the situation), then you can check for the presence of the column:
while (reader.Read())
{
try
{
int paymenIdPos = reader.GetOrdinal("PaymentID");
// if found --> read payment id
int paymentID = reader.GetInt32(paymenIdPos);
}
catch(IndexOutOfRangeException)
{
// if "PaymentID" is not found --> read the "ERrorNumber"
int errorCode = reader.GetInt32("ErrorNumber");
}
}
you can check with GetOrdinal, as marc_s suggested, or like this:
if (reader.GetSchemaTable().Select("ColumnName = 'PaymentId'").Length > 0)
{
//do something here with pamynet
}
else if (reader.GetSchemaTable().Select("ColumnName = 'ErrorNumber'").Length > 0)
{
//do your stuff here with error number
}

Error: "The SqlParameter is already contained by another SqlParameterCollection" when adding a Parameter

I have a few similar functions that interact with my SQL server (selects, calls to stored procdures etc.) and all work with the exception of the one below. Each SqlConnection is contained within a using block with the SqlCommand also contained within a using block.
This code is failing when attempting to add the #LastUpdated parameter. I've tried some suggestions I've seen in other posts: cmd.Parameters.Clear(), wrapping in using, etc., but no luck. A few posts with the same error were resolved when duplicate attempts to set the same parameter where found. It's possible I'm missing that but I've looked over this for a few hours, even cleaned the glasses. Any direction would be appreciated.
private void _AddCartItem(bool hasEventInCart, _EventCart cartContents, ref int cartItemId)
{
using (SqlConnection sqlConnection = new SqlConnection(_striMISConnection))
{
sqlConnection.Open();
using (SqlCommand cmd = sqlConnection.CreateCommand())
{
SqlParameter param = new SqlParameter();
cmd.Parameters.Clear();
// add/update CartItem
if (hasEventInCart)
{
// Update item
cmd.CommandText = "SProc2Insert #CartItemId, #ID, 'Event', #Created, #LastUpdated";
param.ParameterName = "#CartItemId";
param.Value = cartItemId;
cmd.Parameters.Add(param);
}
else
{
// add item
cmd.CommandText = "SProc2Update #ID, 'Event', #Created, #LastUpdated";
}
cmd.CommandType = CommandType.Text;
param.ParameterName = "#Created";
param.Value = DateTime.Now.ToString();
cmd.Parameters.Add(param);
param.ParameterName = "#LastUpdated";
param.Value = DateTime.Now.ToString();
**cmd.Parameters.Add(param);**
param.ParameterName = "#ID";
param.Value = this.ID;
cmd.Parameters.Add(param);
if (hasEventInCart)
{
cmd.ExecuteNonQuery(); // do the update
}
else
{
cartItemId = (int)cmd.ExecuteScalar();
foreach (var currentCartEvent in cartContents.CartEvents)
{
if (currentCartEvent.EventCode == this.EventCode)
{
currentCartEvent.CartItemID = cartItemId;
}
}
}
cmd.Parameters.Clear();
}
}
}
I had the same problem, you can solve it with the code below:
if (SqlParams != null && SqlParams.Count > 0)
{
foreach (SqlParameter spp in SqlParams )
{
SqlParameter nameParam = new SqlParameter(spp.ParameterName, spp.SqlValue);
mycmd.Parameters.Add(nameParam);
}
}
First of all, if you're calling a stored procedure, you need to set your CommandType to CommandType.StoredProcedure - not Text :
cmd.CommandType = CommandType.StoredProcedure;
and just use the stored procedure name as your command query:
cmd.CommandText = "dbo.SProc2Update";
Second, I wouldn't use just a single SqlParameter instance and keep adding that over and over again - I would just use the .Add() method directly - and stop converting all date/time to string! Use the appropriate native datatype they have - DateTime - and specify as such in your Parameters.Add() call:
cmd.Parameters.Add("#Created", SqlDbType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("#LastUpdated", SqlDbType.DateTime).Value = DateTime.Now;
This is how I got this working:
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));

splitting string of value and sending to database

I am trying to split a string of values actually individually and trying to send it into database via Store procedure but i can't figure out that how ?
String to be Split: "2013-03-31,1299,2013-03-31,1099,9888, 0"
CODE:
public bool SqlInsert(String parametersString)
{
//It should be split here
SqlConnection sqlCon = new SqlConnection(conStr);
SqlCommand sqlCom = new SqlCommand("AddCoordinates", sqlCon);
sqlCom.CommandType = CommandType.StoredProcedure;
sqlCom.Parameters.Add("#AddedDateTime", SqlDbType.VarChar).Value = "";
sqlCom.Parameters.Add("#IMEI", SqlDbType.VarChar).Value = "";
sqlCom.Parameters.Add("#RecordedDateTime", SqlDbType.VarChar).Value = "";
sqlCom.Parameters.Add("#Latitude", SqlDbType.VarChar).Value = "";
sqlCom.Parameters.Add("#Longitude", SqlDbType.VarChar).Value = "";
sqlCom.Parameters.Add("#IsParking ", SqlDbType.Bit).Value = true;
try
{
sqlCon.Open();
int NoRows = (int)sqlCom.ExecuteNonQuery();
}
catch (Exception ex) { }
finally
{
sqlCon.Close();
}
return true;
}
Looks to me like it's just comma delimited, in which case try:
string[] parts = "2013-03-31,1299,2013-03-31,1099,9888, 0".Split(',');
However, that makes working with parts a bit awkward, so we can go a step further:
string[] fields = new string[] {"date","imei","recorded_date","lat","lon","is_parking"};
List<string,string> dict = Dictionary<string,string>();
for(var i = 0; i < parts.Length; i++) {
var key = fields[i];
var value = parts[i].Trim(); // You may or may not want to trim the value
dict.Add(key,value);
}
You can then pull the individual fields you want and convert them to the type you need, for example:
int imei = int.Parse(dict["imei"]);
Of course, I'm sidestepping a couple of issues like type conversion failure and disparities between parts and fields, but you get the general idea.
The approach mentioned by #Lloyd is the easiest one.Here is the code for your understanding.
string[] parts = "2013-03-31,1299,2013-03-31,1099,9888, 0".Split(',');
sqlCom.Parameters.Add("#AddedDateTime", SqlDbType.VarChar).Value = parts[0].ToString();
sqlCom.Parameters.Add("#IMEI", SqlDbType.VarChar).Value = parts[1].ToString();
sqlCom.Parameters.Add("#RecordedDateTime", SqlDbType.VarChar).Value = Convert.ToDateTime(parts[2].ToString());
sqlCom.Parameters.Add("#Latitude", SqlDbType.VarChar).Value = parts[3].ToString(); ;
sqlCom.Parameters.Add("#Longitude", SqlDbType.VarChar).Value = parts[4].ToString(); ;
sqlCom.Parameters.Add("#IsParking ", SqlDbType.Bit).Value = ((parts[5].ToString().Trim()).Equals("0"))? true: false;
Hope it helps!

Categories