I have a Windows Forms program I was writing at home (I mostly work with ASP.Net so it's been a while) and I'm having trouble executing stored procedure commands.
I create the SqlCommand object from the SqlConnection object and then create the SqlParameter from the SqlCommand. I specify the name, data type, and so on. However, whenever I call SqlCommand ExecuteReader() it's telling me it expects parameters that were not provided. I clearly added them and can see them populated when stepping through in Debug. Any ideas?
Stored procedure:
EXEC dbo.GetTransactions #StartDate = '2015-04-10 18:07:43',
#EndDate = '2015-04-10 18:07:43'
Class DataAccess:
public static DataTable Execute(SqlCommand iCommand) {
DataTable objTable = new DataTable();
try {
iCommand.Connection.Open();
SqlDataReader objReader = iCommand.ExecuteReader();
objTable.Load(objReader);
objReader.Close();
}
catch {
throw;
}
finally {
iCommand.Connection.Close();
}
return objTable;
}
public static SqlCommand CreateCommand(string iProcedureName) {
try {
SqlConnection objConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConnectionString"].ToString());
SqlCommand objCommand = new SqlCommand(iProcedureName, objConnection);
return objCommand;
}
catch {
throw;
}
}
Class TransactionCollection:
private static DataTable Load(DateTime iStartDate, DateTime iEndDate) {
string strProcedureName = "GetTransactions";
SqlCommand objCommand = DataAccess.CreateCommand(strProcedureName);
SqlParameter param = objCommand.CreateParameter();
param.ParameterName = "#StartDate";
param.DbType = DbType.DateTime;
param.Value = iStartDate;
objCommand.Parameters.Add(param);
param = objCommand.CreateParameter();
param.ParameterName = "#EndDate";
param.DbType = DbType.DateTime;
param.Value = iEndDate;
objCommand.Parameters.Add(param);
return DataAccess.Execute(objCommand);
}
You need to tell your SqlCommand that it's executing a stored procedure! You need to set the CommandType of your SqlCommand - see here:
public static SqlCommand CreateCommand(string iProcedureName) {
try {
SqlConnection objConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["DBConnectionString"].ToString());
SqlCommand objCommand = new SqlCommand(iProcedureName, objConnection);
// add this line here!!
objCommand.CommandType = CommandType.StoredProcedure;
return objCommand;
}
catch {
throw;
}
}
Related
I'm stuck at a loose end with inserting a new data entry into a SQL Server database. I have all the info I want to store in the following class:
public class NewSearchQuery //object reference q
{
public string Name, Location, SearchType, Path, Method;
public int RefNum;
public double Fee;
public bool Paid;
}
and after the user has filled in the form etc.. this is my code to save the info to the database:
bool complete;
string sql = $"Insert into PrivateLog (Id,Applicant,ApplicationDate,Location,Search,Paid,Method,Amount,Files) values({q.RefNum}, '{q.Name}', {AppDate}, '{q.Location}', '{q.SearchType}', {q.Paid}, '{q.Method}', {q.Fee}, '{q.Path}')";
cnn.Open();
try
{
SqlDataAdapter adapter = new SqlDataAdapter();
SqlCommand command = new SqlCommand(sql, cnn); //The Connection String cnn is in a public string variable above this method.
adapter.InsertCommand = new SqlCommand(sql, cnn);
command.Dispose();
complete = true;
}
catch (System.Exception e)
{
complete = false;
}
cnn.Close();
return complete;
Here is what my table designer looks like:
Can anyone show me why the new data entry might not be going through?
You don't need an SqlDataAdapter in that case, you can simply execute your command:
try
{
SqlCommand command = new SqlCommand(sql, cnn);
command.ExecuteNonQuery();
complete = true;
}
Although I recommend using command.Parameters to add your parameters values, protecting a possible SQL injection:
bool complete;
string sql = "Insert into PrivateLog (Id, Applicant, ApplicationDate, Location, Search, Paid, Method, Amount, Files) values(#RefNum, #Name, #AppDate, #Location, #SearchType, #Paid, #Method, #Fee, #Path)";
cnn.Open();
try
{
SqlCommand command = new SqlCommand(sql, cnn);
command.Parameters.Add("#RefNum", SqlDbType.Int).Value = q.RefNum;
command.Parameters.Add("#Name", SqlDbType.VarChar).Value = q.Name;
command.Parameters.Add("#AppDate", SqlDbType.DateTime).Value = AppDate;
command.Parameters.Add("#Location", SqlDbType.VarChar).Value = q.Location;
command.Parameters.Add("#SearchType", SqlDbType.VarChar).Value = q.SearchType;
command.Parameters.Add("#Paid", SqlDbType.Bit).Value = q.Paid;
command.Parameters.Add("#Method", SqlDbType.VarChar).Value = q.Method;
command.Parameters.Add("#Fee", SqlDbType.Decimal).Value = q.Fee;
command.Parameters.Add("#Path", SqlDbType.VarChar).Value = q.Path;
command.ExecuteNonQuery();
command.Dispose();
complete = true;
}
catch (System.Exception e)
{
complete = false;
}
cnn.Close();
return complete;
I want to return a double value from a stored procedure so I can call it from a form and multiplication its value in the value of the text box.
My stored procedure looks like this:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Get_Weight]
#ID INT,
#Weight FLOAT OUTPUT
AS
SELECT #Weight = [Weight]
FROM [Item]
WHERE ID_Item = #ID
This is my data access layer class:
class DataAccessLayer
{
SqlConnection sqlconnection;
public DataAccessLayer()
{
PL.FRM_LOGIN frm = new PL.FRM_LOGIN();
sqlconnection = new SqlConnection("Server='"+System.Environment.MachineName+"';DataBase='"+frm.txtDataBase.Text+"';Integrated Security=true");
}
// Method to open the connection
public void Open()
{
if(sqlconnection.State != ConnectionState.Open)
{
sqlconnection.Open();
}
}
// Method to close the connection
public void Close()
{
if(sqlconnection.State == ConnectionState.Open)
{
sqlconnection.Close();
}
}
// Method to read data from database
public DataTable SelectData(string stored_procedure, SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param != null)
{
sqlcmd.Parameters.AddRange(param);
}
SqlDataAdapter da = new SqlDataAdapter(sqlcmd);
DataTable dt = new DataTable();
da.Fill(dt);
return dt;
}
// Method to insert, update and delete data from database
public void ExecuteCommand(string stored_procedure, SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param != null)
{
sqlcmd.Parameters.AddRange(param);
}
sqlcmd.ExecuteNonQuery();
}
}
I want to create a class in the business layer with a method that can return the value - for example
public void Get_Weight(int ID, double UWeight)
{
DAL.DataAccessLayer DAL = new DAL.DataAccessLayer();
DAL.Open();
SqlParameter[] param = new SqlParameter[2];
param[0] = new SqlParameter("#ID", SqlDbType.Int);
param[0].Value = ID;
param[1] = new SqlParameter("#Weight", SqlDbType.Float);
param[1].Value = UWeight;
param[1].Direction = ParameterDirection.Output;
DAL.ExecuteCommand("Get_Weight", param);
DAL.Close();
}
And after that, I call that method from the form
void CalculateWeight()
{
if (txtLength.Text != string.Empty && cmbName.Text != null)
{
txtWeight.Text = (Convert.ToInt32(txtLength.Text) *(//the code)).ToString();
}
}
Please help me
If this were a code review I would have a number of issues with your approach to a Data Access Layer, but to solve your immediate problem I would suggest you change your Get_Weight method to return a double and not take a UWeight argument. Since your OUTPUT parameter is only set and not also used as input, you can give it a value of DBNull.Value. Lastly, it looks like you might have a typo in your procedure, is the column name really "Wight"?
public double Get_Weight(int ID)
{
DAL.DataAccessLayer DAL = new DAL.DataAccessLayer();
DAL.Open();
SqlParameter[] param = new SqlParameter[2];
param[0] = new SqlParameter("#ID", SqlDbType.Int);
param[0].Value = ID;
param[1] = new SqlParameter("#Weight", SqlDbType.Float);
param[1].Value = DBNull.Value;
param[1].Direction = ParameterDirection.Output;
DAL.ExcuteCommande("Get_Weight", param);
DAL.Close();
double weight = 0.0;
if(double.TryParse(param[1]?.Value?.ToString(), out weight)
{
return weight;
}
else
{
throw new ArgumentException("No Item found for given ID");
}
}
Use ExecuteScalar to get a value from a stored procedure
public double ExcuteCommande(string stored_procedure,SqlParameter[] param)
{
SqlCommand sqlcmd = new SqlCommand();
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.CommandText = stored_procedure;
sqlcmd.Connection = sqlconnection;
if (param!=null)
{
sqlcmd.Parameters.AddRange(param);
}
var back=sqlcmd.ExecuteScalar();
double result;
double.TryParse(back.ToString(), out result);
return result;
}
If I calling a stored proc how do i detect that it has completed succesfully on the server as right now im just doing a try catch which is not the best way of doing this.
public bool deleteTeam(Guid teamId)
{
try
{
string cs = ConfigurationManager.ConnectionStrings["uniteCms"].ConnectionString;
SqlConnection myConnection = new SqlConnection(cs.ToString());
// the stored procedure
SqlCommand cmd = new SqlCommand(
"proc_unitecms_deleteTeam", myConnection);
// 2. set the command object so it knows
// to execute a stored procedure
cmd.CommandType = CommandType.StoredProcedure;
// 3. add parameter to command, which
// will be passed to the stored procedure
cmd.Parameters.Add(
new SqlParameter("#ID", teamId));
return true;
} catch(Exception ex)
{
return false;
}
}
You can return the affected rows number and return -1 in case of catch a exception .
You forget the ExecuteNonQuery.
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
Int32 rowsAffected;
cmd.CommandText = "StoredProcedureName";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
rowsAffected = cmd.ExecuteNonQuery();
sqlConnection1.Close();
My code shown below is create as an inline SQL statement. How can this code be written as a stored procedure??
The code is:
public Stream SelectEmployeeImageByID(int theID)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString());
string sql = "SELECT Image FROM Employees WHERE EmployeeId = #EmployeeId";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#EmployeeId", theID);
connection.Open();
object theImg = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])theImg);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
you can do this
create procedure SelectEmployeeImage(#employee int)
as
begin
SELECT Image FROM Employees WHERE EmployeeId = #EmployeeId
end
then your code will be this form
public Stream SelectEmployeeImageByID(int theID)
{
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString.ToString());
string sql = "SelectEmployeeImage";
SqlCommand cmd = new SqlCommand(sql, connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#EmployeeId", theID);
connection.Open();
object theImg = cmd.ExecuteScalar();
try
{
return new MemoryStream((byte[])theImg);
}
catch
{
return null;
}
finally
{
connection.Close();
}
}
hope this will help you
Creating Stored Procedure
Create procedure SP_InsertEmployee
as
#EmployeeId int
BEGIN
SELECT Image FROM Employees WHERE EmployeeId=#EmployeeId
END
You Should Set CommandType=StoredProcedure and Rest of will be same
cmd.CommandType = CommandType.StoredProcedure;
Recommendations
Always use using which automatically disposes connections
using (SqlConnection con = new SqlConnection())
{
con.open();
using (SqlCommand cmd = new SqlCommand(sql, connection))
{
//object theImg = cmd.ExecuteScalar();
}
con.Dispose();
}
I'm new to C# I need to call a SP and return the table value from C#.
I'm passing current datetime(#currentdate) as my input parameter in the stored procedure.So how do I pass this in C# method?
Pls help me to write a C# method to call that SP and return the value
I have my sp ready. sp will return the top updated record in the table.
I have used this in my C# code
string _Num = null;
SqlConnection sqlConnection1 = new SqlConnection("Data Source=localhost;Initial Catalog=ReferenceDB;Persist Security Info=True;Integrated Security=SSPI");
SqlCommand cmd = new SqlCommand();
Int32 rowsAffected;
Object returnValue;
cmd.CommandText = "Number";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#CurrentDate", DateTime.Now);
cmd.Connection = sqlConnection1;
sqlConnection1.Open();
rowsAffected = cmd.ExecuteNonQuery();
returnValue = cmd.ExecuteScalar();
if (returnValue != null)
_Num = returnValue.ToString();
return _Num
Write his code in that method
SqlConnection con = new SqlConnection("coonectionstring");
SqlCommand cmd = new SqlCommand();
SqlCommand cmd = new SqlCommand("Your sp",con);
cmd.CommandType = CommandType.StoredProcedure;
//input parameters
cmd.Parameters.Add(new SqlParameter("#currentdate",SqlDbType.DateTime,"currentdate"));
int i=command.ExecuteNonQuery();
If you are going to use more than one sp in your C# code, I suggest something like this:
public static DataTable GetSQLValues(string currentDate)
{
SqlParameter[] sqlParams =
{
new SqlParameter("#currentDate", currentDate)
};
return DBHelper.GetTable("MSSQLSPNAME", sqlParams);
}
Use the above for every instance where you need to get table info.
GetTable looks like this:
static SqlConnection _conn;
static string _connStr = ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["primaryConnStr"]].ToString();
static SqlCommand _cmd;
static SqlDataAdapter _dataAdapter = new SqlDataAdapter();
public static DataTable GetTable(string sProcName, SqlParameter[] sqlParams)
{
using (_conn = new SqlConnection(_connStr))
{
_cmd = new SqlCommand(sProcName, _conn);
_conn.Open();
_cmd.CommandType = CommandType.StoredProcedure;
if (sqlParams != null)
{
_cmd.Parameters.AddRange(sqlParams);
}
_dataAdapter = new SqlDataAdapter(_cmd);
var results = new DataTable();
_dataAdapter.Fill(results);
_conn.Close();
return results;
}
}
It will save you a ton of time for each sp call you need from C#.