Return Variable From Stored Procedure - c#

I need to get an employees start date. What I am trying to do is when a check box is checked make a call to the database get the date and return it into my C# code. I think I have everything set-up close to perfect, but my call procedure returns an error. Can someone assist me with setting up syntax so that when a check box is checked it will make a call to the database, run a stored procedure, and return the result (as a datetime) from the stored procedure back into my C# syntax?
EDIT --- The error being thrown is:
cannot implicitly convert type 'System.DateTime' to 'string'
//Calling Procedure
this.txtStartDate.Text = getHireDate(Constants.Database, employeename);
//Actual Procedure
private static string getHireDate(string Database, string employeename)
{
SqlConnection connection = new SqlConnection(Database);
SqlCommand command = new SqlCommand("_uspGetHireDate", connection);
command.CommandType = CommandType.StoredProcedure;
SqlParameter returnValue = new SqlParameter("returnVal", SqlDbType.Int);
returnValue.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnValue);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
//This line throws an error of can not implicitly convert 'System.DateTime' to 'string'
return Convert.ToDateTime(returnValue.Value);
}
//Stored Procedure Being Called
alter procedure [dbo].[_uspGetHireDate]
(
#employeename varchar(100)
)
as
declare #StartDate datetime
set NOCOUNT ON
Set #StartDate = (SELECT CONVERT(VARCHAR(10), HireDate, 101)
FROM tbl_employeeinformation
where hiredate is not null
AND active = 1
AND employeename = #employeename
return #StartDate

Your solution is totally messy. Why are you converting DATE to VARCHAR, then return it as an INT, then converting it as a DateTime and return as STRING???
First of all change your stored procedure to return value standard way. Return DATE, not INT with return:
alter procedure [dbo].[_uspGetHireDate]
#employeename varchar(100)
as
set NOCOUNT ON
SELECT HireDate
FROM tbl_employeeinformation
where hiredate is not null
AND active = 1
AND employeename = #employeename
Then change your method to return DateTime:
private static DateTime getHireDate(string Database, string employeename)
{
SqlConnection connection = new SqlConnection(Database);
SqlCommand command = new SqlCommand("_uspGetHireDate", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
var result = Convert.ToDateTime(command.ExecuteScalar());
connection.Close();
return result;
}
Thanks to #petelids for pointing this out. Change your presentation layer to:
this.txtStartDate.Text = getHireDate(Constants.Database, employeename).ToString("yyyy-MM-dd");
or whatever format that is appropriate. Visualizing data is a work of a presentation layer and not of a business layer. Here you are storing connection string in presentation layer and this is a bit of strange.
Also put your connections, commands etc in using blocks and use try-catch blocks.
Also I have noticed that you are not passing #employeename parameter to your stored procedure.

You are returning DateTime instead of string as intended in function return type
private static string getHireDate(string Database, string employeename)
{
----
return Convert.ToDateTime(returnValue.Value); // Here you are returning datetime but your return type should be string as your function return type is string
}

Related

Why output parameter return 0 at c# level?

I am trying to get output from store procedure but in C# it gives me 0.
public short SelectOccupantTypesByOccupantTypeID(Int64 OccupantID)
{
SqlCommand SqlCom = new SqlCommand("SelectOccupantTypesByOccupantTypeID", DatabaseConnection.OpenConnection());
SqlCom.CommandType = CommandType.StoredProcedure;
SqlCom.Parameters.AddWithValue("#pk_Occupants_OccupantID", OccupantID);
SqlParameter sqlParamOccupantTypeID = new SqlParameter("#OccupantTypeID", SqlDbType.SmallInt);
sqlParamOccupantTypeID.Direction = ParameterDirection.Output;
SqlCom.Parameters.Add(sqlParamOccupantTypeID);
short OccupantTypeID = Convert.ToInt16(sqlParamOccupantTypeID.Value);
SqlCom.ExecuteNonQuery();
DatabaseConnection.CloseConnection();
return OccupantTypeID;
}
trying to get it
protected void ddlOccupants_SelectedIndexChanged(object sender, EventArgs e)
{
Int64 OccupantID= Convert.ToInt64(ddlOccupants.SelectedValue);
Int16 OccupantTypeID= MngOccupants.SelectOccupantTypesByOccupantTypeID(OccupantID);
txtBoxMonthlyInstallment.Text = OccupantTypeID.ToString();
}
SP:
alter PROCEDURE [dbo].[SelectOccupantTypesByOccupantTypeID]
#pk_Occupants_OccupantID bigint,
#OccupantTypeID smallint output
AS
BEGIN
Set #OccupantTypeID= (Select Occupants.OccupantsOccupantTypeID
From Occupants
Where Occupants.pk_Occupants_OccupantID= #pk_Occupants_OccupantID)
return #OccupantTypeID
END
but sp return correct value at sql level but returns 0 at C# level. Why ?
You are reading the value of the parameter before you execute the query, swap the order.
SqlCom.ExecuteNonQuery();
short OccupantTypeID = Convert.ToInt16(sqlParamOccupantTypeID.Value);
However you are commiting other "bad practices", your connections really should be wrapped inside using statements and not reused throughout your program. ADO.NET already implements Connection Pooling, you don't need to do it yourself, just make short lived connections as needed and when you dispose of them they will be returned to the pool.

stored procedure not working properly error converting datatype

Trying to get Username by UserId - I have the following stored procedure:
ALTER PROCEDURE [dbo].[GET_UsernameByUserId_SP](
#UserId int,
#ExecutionResult nvarchar(64) OUTPUT
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SET #ExecutionResult = (SELECT TOP 1 Username FROM UserProfile WHERE UserId = #Userid);
END
Executed by the following method:
public string CallSpRetStr(String spName, SqlParameter[] sqlParams)
{
string sRet = null;
myCommand.CommandType = CommandType.StoredProcedure;
myCommand.CommandText = spName;
myCommand.Parameters.Clear();
myCommand.Parameters.AddRange(sqlParams);
myCommand.Parameters.AddWithValue("#ExecutionResult", DbType.String);
myCommand.Parameters[myCommand.Parameters.Count - 1].Direction = ParameterDirection.Output;
try
{
if (myConnection.State == ConnectionState.Open)
{
myCommand.ExecuteNonQuery();
}
else
{
OpenConnection();
myCommand.ExecuteNonQuery();
CloseConnection();
}
sRet = myCommand.Parameters["#ExecutionResult"].Value.ToString();
}
catch (Exception ex)
{
CloseConnection();
}
return sRet;
}
Called by the following method:
public string GetUsernameByUserId(int UserId)
{
SqlParameter[] parameters = new SqlParameter[1];
parameters[0] = new SqlParameter("#UserId", UserId);
return dal.CallSpRetStr("GET_UsernameByUserId_SP", parameters);
}
At runtime I get the following error message (caught by the try-catch in CallSpRetStr):
'Error converting datatype nvarchar to int'.
I've been banging my head in the wall for more than hour now, trying crazy things etc.
I have two questions:
1. Does anyone understand what is the problem in all the above?
2. Is anyone aware of a better way to get the username by the userid?
Thanks in advance.
This line is incorrect
myCommand.Parameters.AddWithValue("#ExecutionResult", DbType.String);
should be
myCommand.Parameters.AddWithValue("#ExecutionResult", new string(' ', 64);
The AddWithValue method expects, for its second parameter, the current value for the named parameter but you pass an enum (DbType.String == (int)16). AddWithValue then tries to build a parameter with the datatype corresponding to the value passed and thus creates an integer parameter. Of course this is not acceptable by your stored procedure that expects a nvarchar type
Also I would remove any possible misunderstanding on which parameter is the output one using the return value from the AddWithValue instead of an indexing on the parameter collection
SqlParameter p myCommand.Parameters.AddWithValue("#ExecutionResult", new string(' ', 64);
p.Direction = ParameterDirection.Output;
Notice that we need to create a string of the correct size because AddWithValue doesn't know the expected size of the parameter from the stored procedure and so it creates the parameter with the size equals to the length of the string passed.

ExecuteScalar() method is not working properly

I have the following function;
public int GetLoginClaim(IsValidLogin Obj)
{
SqlConnection DBCon = new SqlConnection(ConString);
SqlCommand CmdSelect = new SqlCommand("IsValidLogin", DBCon);
CmdSelect.CommandType = CommandType.StoredProcedure;
DBCon.Open();
try
{
CmdSelect.Parameters.AddWithValue("#UserName", Obj.Username);
CmdSelect.Parameters.AddWithValue("#Password", Obj.Password);
return (int)CmdSelect.ExecuteScalar();
}
catch
{
throw;
}
finally
{
CmdSelect.Dispose();
DBCon.Close();
DBCon.Dispose();
}
}
And the following stored procedure on which it depends;
USE [SMania]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[IsValidLogin]
#UserName varchar(32),
#Password varchar(32)
As
if exists(Select * From NewClientTB Where UserName = #UserName And Password = #Password)
return(1)
else
return(0)
The stored procedure is working correctly when executed on sql server, but when called from the function i posted above, it gives error. The above function is in my data access layer. So in the stack trace, i am having the following error on the above function:
NullReferenceException: Object reference not set to an instance of an object. Can anyone fix this problem?
You need different approach for SPs with return status
Check the example on this MSDN article http://msdn.microsoft.com/en-us/library/ms378371(v=sql.90).aspx
If you want to use ExecuteScalar you need to replace return(X) with select X in SP because it "returns the first column of the first row in the result set" but there is no result set in your SP only return value.
This is how you can get return status in C#
CmdSelect.Parameters.AddWithValue("#UserName", Obj.Username);
CmdSelect.Parameters.AddWithValue("#Password", Obj.Password);
var return_state = CmdSelect.Parameters.Add("#ReturnVal", SqlDbType.Int);
return_state.Direction = ParameterDirection.ReturnValue;
CmdSelect.ExecuteNonQuery();
return (int)return_state.Value;

DateTime from .NET to smalldatetime in SQL - how to do queries?

I have a DateTime component in my code, and I want to use it for a query in my SQL Server database.
When inserting this component, there seems to be no problem, but when querying for smalldatetime values, I just don't know how to do it. The dataset is always empty.
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "ReadDates";
dataset = new DataSet();
SqlParameter parameter = new SqlParameter("#date", SqlDbType.SmallDateTime);
parameter.Value = DateTime.Now();
cmd.Parameters.Add(parameter);
dataAdapter = new SqlDataAdapter(cmd);
dataAdapter.Fill(dataset);
return dataset;
And this is in my stored procedure:
select * from TableDates
where ValueDate <= #date
So I have no problems running the procedure in SQL Server Management Studio, when entering a parameter in this format: '2000-03-03 04:05:01', but when passing a DateTime, the query is always empty. Any suggestions?
I tried it by using SQL Server 2008 R2 Express.
Here is the example stored procedure i wrote:
CREATE PROCEDURE [dbo].[ShowGivenSmallDateTimeValue]
#givenSmallDateTime smalldatetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Simply return the given small date time value back to sender.
SELECT #givenSmallDateTime
END
And here is the C# code to execute the procedure:
var connectionBuilder = new SqlConnectionStringBuilder();
connectionBuilder.DataSource = "localhost\\sqlexpress";
connectionBuilder.IntegratedSecurity = true;
var now = DateTime.UtcNow;
using (var connection = new SqlConnection(connectionBuilder.ConnectionString))
using (var command = new SqlCommand())
{
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "ShowGivenSmallDateTimeValue";
command.Parameters.Add(new SqlParameter("#givenSmallDateTime", SqlDbType.SmallDateTime) { Value = now });
connection.Open();
var result = (DateTime)command.ExecuteScalar();
var difference = result - now;
Console.WriteLine("Due to the smalldatetime roundings we have a difference of " + difference + ".");
}
And it simply works.
Here's my code for creating the SqlParameter for a Datetime; For SQL Server 2008 we pass the value as datetime2 since SQL will implicity convert from datetime2 to every other date type so long as it is within the range of the target type...
// Default conversion is now DateTime to datetime2. The ADO.Net default is to use datetime.
// This appears to be a safe change as any datetime parameter will accept a datetime2 so long as the value is within the
// range for a datetime. Hence this code is acceptable for both datetime and datetime2 parameters, whereas datetime is not
// (because it doesn't handle the full range of datetime2).
SqlParameter sqlParam = new SqlParameter(name, SqlDbType.DateTime2);
Since Your parameter includes zeros in day and month parts...sql server converts it but doest match to your date.... i.e.,
if DATETIME.now() returns '2000-03-03 04:05:01'... it is casted into 2000-3-3 Without including zeros...so u need to specify zeros also to match your date.

Error passing C# DateTime value into SQL Server stored procedure

I am having a problem passing a C# DateTime value to a SQL Server 2005 stored procedure.
The stored procedure takes a parameter of type DateTime and updates a database column with the value passed (column also is datetime type):
ALTER PROCEDURE [dbo].[ProcedureName]
#id int,
#eta datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRANSACTION
UPDATE
TrackingTable
set
ETA = #eta
where
ID = #id
COMMIT TRANSACTION
END
I pass a C# datetime value to the stored procedure by creating a SqlParameter and executing a parameterised non query.
I can see via the analyser that the SQL executed is:
exec ProcedureName #id=19020, #eta='2012-07-17 10:29:34:000'
and if I execute this directly on the database the update works fine, but via my C# program it fails with the error:
The conversion of a char data type to a datetime data type resulted
in an out-of-range datetime value. The statement has been terminated.
I'm sure I'm being daft but I can't for the life of me see whats wrong. PS I'm new to SQL Server!
Any help appreciated!
Thanks.
Sorry the c# code:
dbWrapper.ExecuteProcWithParams("ProcedureName",
dbWrapper.CreateParameter("id", Header.VoyageID),
dbWrapper.CreateParameter("eta", ETA)
ETA is a DateTime Value.
public void ExecuteProcWithParams(string procName, params DbParameter[] parameters)
{
try
{
using (DbCommand cmd = db.CreateCommand())
{
cmd.Transaction = trans;
cmd.CommandText = procName;
cmd.CommandType = CommandType.StoredProcedure;
foreach (DbParameter param in parameters)
{
cmd.Parameters.Add(param);
}
cmd.ExecuteNonQuery();
}
}
catch (Exception)
{
throw;
}
}
public DbParameter CreateParameter(string name, object value)
{
DbParameter result = null;
switch (databaseType)
{
case DatabaseType.SqlServer:
// Sql Server: NULL parameters have to initialised with DBNull rather than NULL
result = new SqlParameter(name, value ?? DBNull.Value);
break;
default:
throw new Exception(String.Format("Unknown database type {0}", databaseType));
}
return result;
}
Try to set uiculture and culture in web.config.
<globalization uiCulture="en-GB" culture="en-GB"/>
Your passing date format and sql date can be different.
So set culture according to your culture.
I just faced a similar problem buddy!
It's because C# converts date time to MM-DD-YYY and SQL server generates date time based on DD-MM-YYYY.
That's why you get an out of bounds error on your month.

Categories