Don't ask me why, but I want put in an sqlCommand object something like this:
sqlConnection a = new sqlConection(...);
sqlCommand b = new sqlCommand("EXEC storedProcedure()", a);
sqlDataAdapter c = new sqlDataAdapter(b);
DataTable d = new DataTable();
c.Fill(d);
So, when the stored procedure makes an insert the row is successfully added but however the code throws an Exception.
I know exist an sqlCommand.CommandType specifically for stored procedures but my architecture need it made in this way.
set the adapter "SelectCommand" property instead
var cmd = new SqlCommand("EXEC storedProcedure()", a);
cmd.CommandType = CommandType.StoredProcedure; //set command property
//..
var adapter = new SqlDataAdapter();
adapter.SelectCommand = cmd; //set adapter command for select query
and your command type must be CommandType.StoredProcedure to exec SP and your architecture don't need this? simply ask him for a good reason.
Your SQL syntax is off.
From http://technet.microsoft.com/en-us/library/ms188332.aspx :
USE AdventureWorks2012;
GO
DECLARE #CheckDate datetime;
SET #CheckDate = GETDATE();
EXEC dbo.uspGetWhereUsedProductID 819, #CheckDate;
GO
So your code should be:
new sqlCommand("EXEC storedProcedure", a);
While there are many ways to do the same thing, there are some things that work best when you do them the way the framework suggests.
In this case there are several things that can happen when you run the stored procedure, depending on which procedure it is. It might return a set of row, or several sets of rows, or nothing at all. There are already things we can do to handle all those situations, courtesy of the .NET framework.
Here's some extension code I've used in the past for any SP that is returning one or more rowsets:
public static DataSet ExecuteStoredProcedure(this SqlConnection connection, string SPName, params object[] parameters)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = SPName;
cmd.CommandTimeout = 60;
if (connection.State != ConnectionState.Open)
connection.Open();
SqlCommandBuilder.DeriveParameters(cmd);
int index = 1;
foreach (object p in parameters)
{
if (index >= cmd.Parameters.Count)
break;
cmd.Parameters[index++].Value = (p == null ? DBNull.Value : p);
}
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
DataSet res = new DataSet();
adapter.Fill(res);
return res;
}
}
}
Handling non-rowset return values and output parameters takes a bit more work, but this will do for your immediate needs:
var conn = new SqlConnection("some connection string");
DataSet ds = conn.ExecuteStoredProcedure("storedProcedure");
DataTable d = ds == null ? null : ds.Tables.Length < 1 ? null : ds.Tables[0];
Related
I would like to migrate database from MS Access to SQL Server and I'm trying to modify my SQL queries. In MS Access they worked.
I have this C# code:
private DataSet GetIncident_ByIncident(string inc_num)
{
MainIncident mi = new MainIncident();
mi.incident_full_number = inc_num;
string query = #"SELECT MainIncidentTable.Incident_Full_Num ,
MainIncidentTable.Customer_Name ,
MainIncidentTable.Service_Representative ,
MainIncidentTable.Incident_Date ,
MainIncidentTable.Average_Invoice ,
MainIncidentTable.Street ,
MainIncidentTable.City ,
MainIncidentTable.Contact ,
IncidentStatuses.Incident_Status_Name,
Stations.Station_Name
FROM(MainIncidentTable INNER JOIN
Stations ON MainIncidentTable.Current_Station_ID = Stations.Station_ID)
INNER JOIN IncidentStatuses ON MainIncidentTable.Current_Incident_Status_Id = IncidentStatuses.Incident_Status_Id
WHERE Incident_Full_Num = '#Incident_Full_Num'";
List<OleDbParameter> l = new List<OleDbParameter>();
l.Add(new OleDbParameter("#Incident_Full_Num", mi.incident_full_number));
l.Add(new OleDbParameter("#Customer_Name", mi.customer_name));
l.Add(new OleDbParameter("#Service_Representative", mi.service_representative));
l.Add(new OleDbParameter("#Incident_Date", mi.incident_date));
l.Add(new OleDbParameter("#Average_Invoice", mi.average_invoice));
l.Add(new OleDbParameter("#Street", mi.street));
l.Add(new OleDbParameter("#City", mi.city));
l.Add(new OleDbParameter("#Contact", mi.contact));
l.Add(new OleDbParameter("#Current_Station_ID", mi.current_station_id));
l.Add(new OleDbParameter("#Current_Incident_Status_Id", mi.current_incident_status_id));
var con = GetDataSetWithParameters(query, l);
return con;
}
Connection method :
public static DataSet GetDataSetWithParameters(string query, List<OleDbParameter> parameters)
{
DataSet ds = new DataSet();
OleDbConnection Con = new OleDbConnection(sqlConnectionString);
Con.Open();
try
{
using (OleDbCommand cmd = new OleDbCommand(query, Con))
{
if (parameters != null)
{
cmd.Parameters.AddRange(parameters.ToArray());
}
using (OleDbDataAdapter Adapter = new OleDbDataAdapter(cmd))
{
Adapter.Fill(ds);
}
return ds;
}
}
catch
{
throw;
}
finally
{
CloseConnection(ref Con);
}
}
SQL query is working but not returning rows. I guess that problem is a syntax of parameter in query.
Can someone direct me?
You must not enclose your parameters in quotes. The library will take care of that. Ie use
WHERE Incident_Full_Num = #Incident_Full_Num
instead of
WHERE Incident_Full_Num = '#Incident_Full_Num'
EDIT
Oh sorry, forgot, that OleDb doesn't use named parameters but only positional parameters. See docs
So either update your query to
WHERE Incident_Full_Num = ?
or you use SqlCommand and SqlParameter instead of OleDbCommand and OleDbParameter.
Be aware, that if you use OleDbCommand the order in which you pass the parameters is important. Ie, the first ? will be bound to the first parameter, the second ? to the second parameter and so on. If you need the same parameter in your query twice, you would also need to pass it twice.
Furthermore it seems, only the first parameter is used. Why are you passing numerous unused parameters to your command?
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'm using stored procedure to get the 'password' value from the database. and i need to assign this value to a variable. I'm using asp.net- mvc and Ado.net.
Here is my stored procedure.
CREATE PROCEDURE [dbo].[getPassword]
(
#Email VARCHAR(100)
)
AS
BEGIN
SELECT Password FROM dbo.Staff_Login WHERE Email=#Email
END
Here is my repository class.
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
namespace Job_Recuitment_System.Repository
{
public class LoginRepository
{
private SqlConnection con;
//To handle sql connection
private void connection() {
string constr = ConfigurationManager.ConnectionStrings["mycon"].ToString();
con = new SqlConnection(constr);
}
//to get the password
public List<StaffLogin> getPassword(StaffLogin obj) {
connection();
List<StaffLogin> pword = new List<StaffLogin>();
SqlCommand com = new SqlCommand("getPassword", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Email",obj.Email);
SqlDataAdapter da = new SqlDataAdapter(com);
DataTable dt = new DataTable();
con.Open();
da.Fill(dt);
con.Close();
//Bind StaffLogin
pword = (from DataRow dr in dt.Rows
select new StaffLogin()
{
Password = Convert.ToString(dr["Password"]),
}).ToList();
return pword;
}
}
}
I have use a list. But i need to assign value to a varible. because i only i need is one value (password).
You don't need an SqlDataAdapter but you just use the SqlCommand.ExecuteScalar
connection();
SqlCommand com = new SqlCommand("getPassword", con);
com.CommandType = CommandType.StoredProcedure;
com.Parameters.Add("#Email",SqlDbType.NVarChar, 100). Value = obj.Email;
con.Open();
var result = com.ExecuteScalar();
if(result != null)
MessageBox.Show("Password = " + result.ToString();
con.Close();
ExecuteScalar returns the first column of the first row retrieved by the command and your query fits nicely this condition. However it is important to consider that ExecuteScalar could return NULL if the query doesn't produce any result so always test the result against a null value before using it.
On another matter I really suggest you to avoid stored procedures for these simple menial tasks unless there is a good reason to use them. Using the Add instead of AddWithValue and specifying the exact size of the parameter gives to the Sql optimizer enough hints to create an optimized query.
Finally, remember that storing/returning passwords in clear text is considered a very big security risk. Try to use a safer method as explained in this question: Best way to store passwords in a database
In this case you are retrieving the value of a single column, You can use ExecuteScalar() in such situations. Then the command execution will be like the following:
string passwordStr= (string)com.ExecuteScalar();
So the signature of the getPassword method will also be changed, its return type will become string instead for List<StaffLogin>; the new signature will be:
public string getPassword(StaffLogin obj)
{
connection();
string passwordStr = String.Empty;
using (SqlCommand com = new SqlCommand("getPassword", con))
{
com.CommandType = CommandType.StoredProcedure;
com.Parameters.AddWithValue("#Email", obj.Email);
passwordStr = (string)com.ExecuteScalar();
}
return passwordStr;
}
I'm new to using SqlDataAdpter and I'm trying to execute a stored procedure. The stored procedure executes successfully but no rows are returned. I've used SQL Server Profiler to monitor the call and it runs successfully (I can copy and execute the query from profiler without modifying it and get results).
I have the following:
public ActionResult Index()
{
SqlConnection conn = null;
DataSet results = null;
try
{
string connectionString = // ... my connection
conn = new SqlConnection(connectionString );
string query = #"usp_mySP";
conn.Open();
SqlDataAdapter sqlAdpt = new SqlDataAdapter(query, conn);
sqlAdpt.SelectCommand.CommandType = CommandType.StoredProcedure;
var dataDate = new SqlParameter { ParameterName = "#DataDate", Value = DateTime.Now };
var idList = new SqlParameter { ParameterName = "#IDList", Value = "1231,2324,0833" };
sqlAdpt.SelectCommand.Parameters.Add(dataDate);
sqlAdpt.SelectCommand.Parameters.Add(idList);
results = new DataSet();
sqlAdpt.Fill(results);
sqlAdpt.Dispose();
}
catch (SqlException e)
{
throw new Exception("Exception:" + e.Message);
}
finally
{
if (conn != null)
conn.Close();
}
return View(results);
}
When I inspect the DataSet through the debugger, it always returns 0 rows.
Please help with what I'm doing wrong?
Note: I've also tried (but do NOT prefer) executing as a SQL command:
EXEC usp_mySP #DataDate, #IDList
and it didn't work either as I got int to varchar conversion errors.
I think you try to add SqlParameter using SqlCommand like this :
SqlCommand cmd = new SqlCommand();
cmd.parameter.addwithvalue(#DataDate,DateTime.Now);
So the reason was because of set nocount on. I added it to my sp and it works. Thank you everyone for clarifying.
This is a question from an experienced beginner!
Using ASP.NET 4 C# AND SQL server,
I have a connection string in web.config to myDatabase named "myCS".
I have a database named myDB.
I have a table named myTable with a primary key named myPK
What are the NECESSARY lines of code behind (minimal code) to create a SQL connection, then select from myTable where myPK=="simpleText"
it will probably include:
sqlconnection conn = new sqlconnection(??? myCS)
string SQLcommand = select * from myDB.myTable where myPK==myTestString;
sqlCommand command = new SqlCommand(SQL,conn);
conn.Open();
booleanFlag = ????
conn.Close();
conn.Dispose();
then
If ( theAnswer != NULL ) // or (if flag)
{
Response.Redirect("Page1.aspx");
}
else
{
Response.Redirect("Page2.aspx");
}
Here is a limited simple tutorial:
First, you want to have a class to do the hard work for you, then you will use it with ease.
First, you have to crate the connection string in your web.config file and name it.
Here it is named DatabaseConnectionString, but you may named it myCS as required in the question.
Now, in App_Code create a new class file and name it SqlComm (this is just an example name) like:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
public class SqlComm
{
// this is a shortcut for your connection string
static string DatabaseConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["dbConStr"].ConnectionString;
// this is for just executing sql command with no value to return
public static void SqlExecute(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
// with this you will be able to return a value
public static object SqlReturn(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
object result = (object)cmd.ExecuteScalar();
return result;
}
}
// with this you can retrieve an entire table or part of it
public static DataTable SqlDataTable(string sql)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Connection.Open();
DataTable TempTable = new DataTable();
TempTable.Load(cmd.ExecuteReader());
return TempTable;
}
}
// sooner or later you will probably use stored procedures.
// you can use this in order to execute a stored procedure with 1 parameter
// it will work for returning a value or just executing with no returns
public static object SqlStoredProcedure1Param(string StoredProcedure, string PrmName1, object Param1)
{
using (SqlConnection conn = new SqlConnection(DatabaseConnectionString))
{
SqlCommand cmd = new SqlCommand(StoredProcedure, conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter(PrmName1, Param1.ToString()));
cmd.Connection.Open();
object obj = new object();
obj = cmd.ExecuteScalar();
return obj;
}
}
}
Okay, this only a class, and now you should know how to use it:
If you wish to execute a command like delete, insert, update etc. use this:
SqlComm.SqlExecute("TRUNCATE TABLE Table1");
but if you need to retrieve a specific value from the database use this:
int myRequiredScalar = 0;
object obj = new object();
obj = SqlComm.SqlReturn("SELECT TOP 1 Col1 FROM Table1");
if (obj != null) myRequiredScalar = (int)obj;
You can retrieve a bunch of rows from the database this way (others like other ways)
This is relevant to your sepecific question
int Col1Value = 0;
DataTable dt = new DataTable();
dt = SqlComm.SqlDataTable("SELECT * FROM myTable WHERE myPK='simpleText'");
if (dt.Rows.Count == 0)
{
// do something if the query return no rows
// you may insert the relevant redirection you asked for
}
else
{
// Get the value of Col1 in the 3rd row (0 is the first row)
Col1Value = (int)dt.Rows[2]["Col1"];
// or just make the other redirection from your question
}
If you need to execute a stored procedure with or without returning a value back this is the way to do that (in this example there are no returning value)
SqlComm.SqlStoredProcedure1Param("TheStoredProcedureName", "TheParameterName", TheParameterValue);
Again, for your specific question return the table using the SqlDataTable , and redirect if dt.Rows.Count >0
Have fun.
There are many ways: LINQ, SqlDataReader, SQLDataAdapter, according to what you want to read (single value, datatable ...), so here is an example:
using (SqlConnection con = new SqlConnection("SomeConnectionString"))
{
var cmd = new SqlCommand("select from myTable where myPK==N'"+ simpleText+ "'",con);
cmd.Connection.Open();
var sqlReader = cmd.ExecuteReader();
while(sqlReader.Read())
{
//Fill some data like : string result = sqlReader("SomeFieldName");
}
sqlReader.Close();
cmd.Connection.Close();
cmd.Dispose();
}