I have a stored procedure it returns a name so i need to get the name in in C#
so i just execute the Sp from C# and read the out put using ExecuteReader() like below
using (var objCommand = new SqlCommand("SpName", objConnection))
{
objCommand.Parameters.AddWithValue("#Param1", Param);
objCommand.Parameters.AddWithValue("#Purpose", Purpose);
objConnection.Open();
objCommand.CommandType = CommandType.StoredProcedure;
using (var reader = objCommand.ExecuteReader())
{
while (reader.Read())
{
objemailsend.Name = Convert.ToString(reader["Name"]);
}
}
}
objConnection.Close();
It gives an exception
Index Out of range exception
I am sure that the index names are same i mean the Sp also returns the same name
Name
----
name1
like above
then i tried something like below and now the exception disappears and it returns a numeric value i don't know from where the value coming from and it is not same as my SP result
objexample.Name = reader[0].ToString();
also tried
using (var reader = objCommand.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
objemailsend.Name = Convert.ToString(reader["Name"]);
}
}
}
But the same error
Can you somebody help me to solve my issue.
Please check this answer out
var returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int);
returnParameter.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
int id = (int) returnParameter.Value;
Try retrieving the value using index like objemailsend.Name = reader[1].ToString().
Where I have assumed 1 to be the index for name column.
As you are getting the Index Out of range execption this will help because here you are explicitly providing the index for the name column.
using (var objCommand = new SqlCommand("SpName", objConnection))
{
objCommand.Parameters.AddWithValue("#Param1", Param);
objCommand.Parameters.AddWithValue("#Purpose", Purpose);
objConnection.Open();
objCommand.CommandType = CommandType.StoredProcedure;
using (var reader = objCommand.ExecuteReader())
{
while (reader.Read())
{
objemailsend.Name = Convert.ToString(reader[1]);
}
}
}
objConnection.Close();
Related
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?
I wrote up this function to return a dataset, I was expecting a smaller dataset as there's only one value I was expecting back, but I get a rather bloated object back which I cannot find the value I am looking for, this is causing problems as I intend to use this function heavily.
I was hoping someone could spot what I am doing wrong, I have included the code, a screenshot of the returned object and what I am expecting. Any help would be greatly appreciated.
If I have not phrased anything in this question correctly feel free to let me know, I struggle to express my thoughts well.
public DataSet getPartnerParameter(string parameter)
{
using (var dbConnection = new SqlConnection(UnityHelper.IocContainer.Resolve<IConfigHelperService>().GetConnectionString("CASConnectionString")))
{
dbConnection.Open();
using (var dbCommand = new SqlCommand("GETPARTNERPARAMETER"))
{
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Connection = dbConnection;
SqlParameter lstrParameter = new SqlParameter("#Parameter", SqlDbType.VarChar);
lstrParameter.Value = parameter;
dbCommand.Parameters.Add(lstrParameter);
var ldaDPS = new SqlDataAdapter(dbCommand);
var ldstParameterValues = new DataSet();
ldaDPS.Fill(ldstParameterValues);
return ldstParameterValues;
}
}
}
This is what I am expecting to find
edit//
changed my code slightly but still not working.
public String[] getPartnerParameter(string parameter)
{
using (var dbConnection = new SqlConnection(UnityHelper.IocContainer.Resolve<IConfigHelperService>().GetConnectionString("CASConnectionString")))
{
dbConnection.Open();
SqlCommand dbCommand = new SqlCommand("GETPARTNERPARAMETER", dbConnection);
dbCommand.CommandType = CommandType.StoredProcedure;
SqlParameter lstrParameter = new SqlParameter("#Parameter", SqlDbType.VarChar);
lstrParameter.Value = parameter;
dbCommand.Parameters.Add(lstrParameter);
SqlDataReader reader = dbCommand.ExecuteReader();
string[] results = new string[2];
while (reader.Read())
{
results[0] = reader[0].ToString();
results[1] = reader[1].ToString();
}
if (results.Length < 1)
{
results[0] = "Cannot find Value";
results[1] = "S";
return results;
}
else
{
return results;
}
}
The error is this:
{"Procedure or function 'GETPARTNERPARAMETER' expects parameter '#Parameter', which was not supplied."}
The values you are looking for are probably in the dataSet.Tables[0].Rows[0] row.
However, if you are expecting one row back, a DataSet object seems like overkill. I would recommend avoiding the SqlDataAdapter/DataSet and instead use a SqlDataReader.
Untested code, but should give you the gist of how to use it:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand dbCommand = new SqlCommand("GETPARTNERPARAMETER", connection);
dbCommand.CommandType = CommandType.StoredProcedure;
SqlParameter lstrParameter = new SqlParameter("#Parameter", SqlDbType.VarChar);
lstrParameter.Value = "LexisNexisCreditConsentRequired";
dbCommand.Parameters.Add(lstrParameter);
SqlDataReader reader = dbCommand.ExecuteReader();
while (reader.Read())
{
var yourValue = reader[0];
var yourDataType = reader[1];
}
}
A DataSet is an object which can contain many tables. It doesn't have to, but it can, and so it also has a number of fields, properties, and methods to support that role.
For this query, look at ldstParameterValues.Tables[0].Rows[0]. Within that row, you can also see the columns with another level of bracket-indexing:
DataRow row = ldstParameterValues.Tables[0].Rows[0];
var column0Value row[0];
var column1Value = row[1];
However, the type for these results is object. You'll need to either cast the values or use one of the GetX() methods on the datarow to get results with a meaningful type.
I know people are going to scream that this topic is all over the internet. I know, I've read them. And I still don't understand it. I simply want to populate my object from the results of a stored procedure. Now this stored procedure takes at least 2 parameters - an action and what to find.
#Action
#customername
The #Action simply determine what the stored procedure needs to do and returns the results. So for example if I want to update a customer, I'd call the sp through my object:
public class Customer()
{
//properties
public int UpdateCustomer()
{
using (SQLConnection connection = new SqlConnection(Helper.CnnVal("DataConnection")))
{
SQLCommand = new SqlCommand(Helper.Procedure("Customer"), connection);
command.CommandType = CommandType.StoredProcedure;
SqlParameterCollection parameterCollection = command.Parameters;
parameterCollection.Add("#Action", SqlDbType.NVarChar, -1).Value = "Update"
//complete the rest of it....
}
}
}
This works well. So the problem arises when I simply want to populate the object with the results of the sp. In this case I would pass "Retrieve" as the #Action parameter and this.customer_name as the #customername parameter to the sp.
But how do I put the results from the stored procedure into the object?
I have this...
public void GetCustomer()
{
using (SQLConnection connection = new SqlConnection(Helper.CnnVal("DataConnection")))
{
var retrieval = new DynamicParameters();
retrieval.Add("#Action", "Retrieve");
retrieval.Add("#name", this.customer_Name);
connection.Open():
connection.Execute(Helper.Procedure("Customer"), retrieval, commandType: CommandType.StoredProcedure);
}
}
But I don't think it's working.
Back a long time ago I used to run a "fetch" for PHP when I needed to populate an object. Should I go back to this?
You need to execute a SqlReader on the command, Something like this:
using (var connection = new SqlConnection("Connection"))
using (var command = new SqlCommand("Retrieve", connection))
{
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.AddWithValue("#Action", "Retrieve");
command.Parameters.AddWithValue("#name", this.customer_Name);
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var item = new YourClass();
// You can use GetX() methods to get the value of the fields
item.Name = reader.GetString("name");
// You can also access the fields by using bracket notation
item.Age = (int)reader["age"];
// Be careful of nullable fields though!
}
}
}
Using #Encrypt0r advice and guidance I got it working:
public void GetCustomer() {
using (SqlConnection connection = new SqlConnection(Helper.CnnVal("DataConnection"))) {
SqlCommand command = new SqlCommand(Helper.Procedure("Customer"), connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#Action", "Retrieve");
command.Parameters.AddWithValue("#name", this.customer_name);
connection.Open();
using (var reader = command.ExecuteReader()) {
while (reader.Read()) {
this.tbl_id = (int)reader["tbl_id"];
this.customer_name = (string)reader["customer_name"];
this.customer_id = reader.GetInt32(customer_id);
this.customer_address = (string)reader["customer_address"];
this.customer_city = (string)reader["customer_city"];
this.customer_state = (string)reader["customer_state"];
this.customer_zip = reader.GetInt32(customer_zip);
}
}
I am trying to query the MySQL database from a c# application. Below is the code , here I am using parameterized query
public static void ValidateName(MySqlConnection conn,List<Employee> EmpList, string Group)
{
string selectQuery = "Select Name from Employee where Group = #Group AND #Name in (FirstName, LastName);";
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
for (int i = 0; i < EmpList.Count; i++)
{
cmd.Parameters.Add("#Group", MySqlDbType.VarChar).Value = Group;
cmd.Parameters.Add("#Name", MySqlDbType.VarChar).Value = EmpList[i].Name;
var reader = cmd.ExecuteReader();
List<string> lineList = new List<string>();
while (reader.Read())
{
lineList.Add(reader.GetString(0));
}
if (lineList.Count <=0)
{
WriteValidationFailure(EmpList[i], "Failed");
}
}
}
But the above code is throwing error in below line saying
cmd.Parameters.Add("#Group", MySqlDbType.VarChar).Value = Group;
An unhandled exception of type 'MySql.Data.MySqlClient.MySqlException'
occurred in MySql.Data.dll' #Group has already been defined
This is happening because you are adding the same set of parameters in each iterations. You can either clear then in each iteration or else add them before starting the loop and change the value of existing parameter during each iteration. I think second option would be great. One more thing I have to specify here is about the reader, you have to use reader as an using variable so that each time it will get disposed at the end of the using block and your code works fine. Which means you can try something like this:
using (MySqlCommand cmd = new MySqlCommand(selectQuery, conn))
{
cmd.Parameters.Add(new MySqlParameter("#Group", MySqlDbType.VarChar));
cmd.Parameters.Add(new MySqlParameter("#Name", MySqlDbType.VarChar));
for (int i = 0; i < EmpList.Count; i++)
{
cmd.Parameters["Group"].Value = group;
cmd.Parameters["Name"].Value = EmpList[i].Name;
// rest of code here
using (MySqlDataReader reader = cmd.ExecuteReader())
{
// Process reader operations
}
}
}
I'm updating some old legacy code and I ran into a problem with the
SqlCommand.ExecuteReader() method. The problem is that it's not returning any
results. However, using SqlDataAdapter.Fill(), I get results back from the
database. What am I doing wrong? How can I get results back using the data
reader?
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
using (var sqlCommand = new SqlCommand())
{
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "SELECT * FROM MyTable WHERE ID = 1";
sqlConnection.Open();
// This code works.
//var dataTable = new DataTable();
//using (var sqlDataAdapter = new SqlDataAdapter(sqlCommand))
//{
// sqlDataAdapter.Fill(dataTable);
//}
// This code is not working.
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}
Could it be that there is no Int32 in your results ?
var id = sqlDataReader.GetInt32(0); // <-- this might not be an Int32
Either try:
var id = sqlDataReader.GetValue(0);
Or cast to the correct type (BIGINT for example is Int64), not sure without seeing your data.
Try this..
var id = 0;
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
id = sqlDataReader.GetInt32(sqlDataReader.GetOrdinal("ColName"));
}
}
I have moved the variable outside of the reader code or the variable will only be accessible inside that scope. I would avoid specifying the ordinal in the code, in case someone altered the columns in the DB.
Also, specify the columns in the SQL statement... SELECT ColName FROM ... and use params in the query
If you got to that line then it has results
Does not mean the value is not null
And you should not use a SELECT *
If may have a problem with an implicit cast
Try Int32
try
{
if(sqlDataReader.IsDBNull(0))
{
// deal with null
}
else
{
Int32 id = sqlDataReader.GetInt32(0);
}
}
catch (SQLexception Ex)
{
Debug.WriteLine(Ex.message);
}
var connectionString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString();
using (var sqlConnection = new SqlConnection(connectionString))
{
sqlConnection.Open();
string sql = "SELECT * FROM MyTable WHERE ID = 1";
using (var sqlCommand = new SqlCommand(sql, sqlConnection))
{
using (var sqlDataReader = sqlCommand.ExecuteReader())
{
while (sqlDataReader.Read())
{
// This fails because the data reader has no results.
var id = sqlDataReader.GetInt32(0);
}
}
}
}