Set date and time in stored procedure - c#

I am currently having a problem printing the output using C# asp.net. I've built a stored procedure containing a query that will select the username if the login date and time that the user is trying to login on the website is in between a specific start and end time. So here is my code using sql server:
CREATE PROCEDURE [dbo].[access]
(#DateNow as varchar(50),
#studentnum as varchar(50)
)
AS
IF EXISTS(SELECT StudentNum
FROM users, enlistment
WHERE StudentNum LIKE '13%'
AND #DateNow BETWEEN '2016-09-28 00:00:00.000' AND endtime)
SELECT username FROM users, enlistment
WHERE StudentNum LIKE '13' + #studentnum
AND #DateNow BETWEEN starttime AND endtime
Here is my code in c#
SqlCommand cmd3 = new SqlCommand("access", connection);
SqlParameter useraccess = new SqlParameter("studentnum", fourNum);
string datenow = DateTime.Now.ToString("MMMM dd yyyy hh:mm");
SqlParameter date = new SqlParameter("DateNow", datenow);
cmd3.Parameters.Add(useraccess);
cmd3.Parameters.Add(date);
cmd3.CommandType = CommandType.StoredProcedure;
lblStatus.Text = Convert.ToString(cmd3.ExecuteScalar());
After executing, lblStatus.Text should display the username of the person trying to login. unfortunately, the website is not showing it. Is there a problem in my code?

This is a fix on your use of Date, not an answer as to why you are not getting the expected result.
Always use the native data types in .net and sql server, never a string representation of the type!
Changed sp signature
CREATE PROCEDURE [dbo].[access]
(#DateNow as Date, -- change this to Date or DateTime or DateTime2 accordingly
#studentnum as varchar(50)
)
-- rest of stored proc does not have to change
Changed c# code
SqlParameter date = new SqlParameter("#DateNow", SqlDbType.Date) {Value = System.DateTime.Now.Date};
// or with time
// SqlParameter date = new SqlParameter("#DateNow", SqlDbType.DateTime) {Value = System.DateTime.Now};

Related

Data Table Always getting empty

I am trying to display report in mvc web application using rdlc. I have created data set and data table. but now report viewer always reloading continuously. when i try to figure out the problem i found this issue.
Here C# Code
private DataTable GetData(DateTime sdate, DateTime edate,string user,string sp_name)
{
DataTable oDataTable = new DataTable();
string ConStr = System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
using (SqlConnection con = new SqlConnection(ConStr))
{
SqlCommand cmd = new SqlCommand("GetBalanceSheet_CurrentUser", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#SDate", SqlDbType.DateTime).Value = sdate;
cmd.Parameters.Add("#EDate", SqlDbType.DateTime).Value = edate;
cmd.Parameters.Add("#Uid", SqlDbType.VarChar).Value = user;
SqlDataAdapter oSqlDataAdapter = new SqlDataAdapter(cmd);
oSqlDataAdapter.Fill(oDataTable);
}
return oDataTable;
}
Here Sql Stored Procedure
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- GetBalanceSheet_CurrentUser '2017-09-12' ,'2017-11-12' ,'ab0eb318-de5f-4f13-a80b-7a95f678ad8a'
ALTER PROCEDURE [dbo].[GetBalanceSheet_CurrentUser]
#SDate DateTime,#EDate DateTime,#Uid VarChar(MAX)
AS
IF OBJECT_ID ('tempdb..#TEMP1') IS NOT NULL
DROP TABLE #TEMP1
IF OBJECT_ID ('tempdb..#TEMP2') IS NOT NULL
DROP TABLE #TEMP2
DECLARE #UserId VarChar(MAX)
SELECT #UserId = #Uid
SELECT ROW_NUMBER() OVER(ORDER BY Date) RNo,Description,Date,Amount,ForUser,CreatedUser,Status,ApprovedBy
INTO #TEMP1
FROM (
SELECT PEDM.ProjectExpenditureDescription AS Description , PEDM.ExpendedDate As Date,PEDM.ProjectExpenditureCost As Amount, ANU1.UserName As ForUser,ANU1.UserName As CreatedUser,PEDM.ApprovedStatus As Status,ANU2.UserName As ApprovedBy
FROM ProjectExpenditureDetailsModel PEDM
JOIN AspNetUsers ANU1
ON ANU1.Id = PEDM.CreatedUser
JOIN AspNetUsers ANU2
ON ANU2.Id = PEDM.ApprovedBy
WHERE PEDM.IsActive = 1
AND PEDM.IsDelete = 0
AND PEDM.Rejected = 0
AND PEDM.CreatedUser = #UserId
UNION ALL
SELECT OMDM.ObtainedMoneyDescription As Description,OMDM.ObtainedDate As Date,(OMDm.ObtainedMoneyAmount *-1) As Amount, ANU3.UserName As ForUser,ANU4.UserName As CreatedUser,OMDM.ApprovedStatus,ANU5.UserName As ApprovedBy
FROM ObtainedMoneyDetailsModel OMDM
JOIN AspNetUsers ANU3
ON ANU3.Id = OMDM.ForUser
JOIN AspNetUsers ANU4
ON ANU4.Id = OMDM.CreatedUser
JOIN AspNetUsers ANU5
ON ANU5.Id = OMDM.ApprovedBy
WHERE OMDM.IsActive = 1
AND OMDM.IsDelete = 0
AND OMDM.Rejected = 0
AND OMDM.ForUser = #UserId
)A
ORDER BY Date
SELECT RNo,Description,Convert (varchar(20),Date,103) AS ConvertedDate,Date,Amount,SUM(Amount) OVER (ORDER BY RNo) AS Balance,ForUser,CreatedUser,Status,ApprovedBy
INTO #TEMP2
FROM #TEMP1
SELECT RNo,Description,ConvertedDate,Date,Amount,Balance,ForUser,CreatedUser,Status,ApprovedBy
FROM #TEMP2
WHERE Date Between #SDate AND #EDate
When I execute program sql profiler indicates it hits successfully. but when i return result to data table its always getting empty.
I have executed sp manually using same parameters. it is showing 10
records.but when i call through my c# code its hitting but sql data
adapter always empty like {}
Do you execute your sp manually under the same account?
Your procedure uses datetime parameters but the literals for this parameters that you are passing in are language dependent.
Instead, you should pass them in language independent format yyyymmdd (without any separator)
Now, your login language is different from the default login of your application, this cause the date literals to be interpreted differently.
Here is an example to show you the problem. First execute it as it is, then comment set language us_english and uncomment set language British;
declare #t table (dt datetime);
insert into #t values ('20171001'), ('20171101'); -- added 1st oct + 1st nov
--set language British;
set language us_english;
declare #SDate datetime ='2017-09-12', #EDate datetime = '2017-11-12';
select *
from #t
WHERE dt Between #SDate AND #EDate;

Correct Format of sending DatetimePicker's Date value to SQL Server

SQL Server has the following Columns in the "Crash" Table
(<NationalId, char(10),>
,<CrashTime, date,>
,<CrashLocation, nvarchar(50),>
,<City, nvarchar(50),>
,<CarColor, nvarchar(50),>
,<CarEngine, nvarchar(50),>
,<CarType, nvarchar(50),>
,<Damage, int,>)
There is a Stored Procedure Called "addCrash" with following codes:
ALTER Procedure [dbo].[addCrash]
#NationalId char(10),
#CrashTime date,
#CrashLocation nvarchar(50),
#City nvarchar(50),
#CarColor nvarchar(50),
#CarEngine nvarchar(50),
#CarType nvarchar(50),
#Damage int
AS
BEGIN
INSERT INTO [dbo].[Crash]
([NationalId]
,[CrashTime],
[CrashLocation]
,[City]
,[CarColor]
,[CarEngine]
,[CarType]
,[Damage])
VALUES
( #NationalId,
#CrashTime ,
#CrashLocation ,
#City ,
#CarColor ,
#CarEngine ,
#CarType ,
#Damage)
END
Now in Visual Studio i use a DateTimePicker with the custom format of yyyy-MM-dd to send date to "CrashTime" column, the problem is whenever i try to add date from DateTimePicker to my database, There is error of not sending "CrashTime"(the date) Properly.
private void button1_Click(object sender, EventArgs e)
{
SqlParams[] parameters = new SqlParams[]
{
new SqlParams("#NationalId", SqlDbType.Char, nationalId),
new SqlParams("#CrashTime", SqlDbType.Date, dateTimePicker1.Value.Date.ToString("yyyy-MM-dd")),
new SqlParams("#CrashLocation", SqlDbType.NVarChar, TxtCrashLocation.Text),
new SqlParams("#City", SqlDbType.NVarChar, cityCombo.SelectedValue.ToString()),
new SqlParams("#CarColor", SqlDbType.NVarChar, ColorCombo.SelectedValue.ToString()),
new SqlParams("#CarEngine", SqlDbType.NVarChar, EngineCombo.SelectedValue.ToString()),
new SqlParams("#CarType", SqlDbType.NVarChar, cartypeCombo.SelectedValue.ToString()),
new SqlParams("#Damage", SqlDbType.Int, TxtDamage.Text)
};
ModifyConnection mc = new ModifyConnection();
mc.AddRecord("exec addCrash #NationalId,#CrashTime,#CrashLocation,#City,#CarColor,#CarEngine,#CarType,#Damage", parameters);
MessageBox.Show("Crash added Successfuly");
}
I have no idea about the root of problem, even i get the value of DateTimePicker to a string the format sounds correct and is: 2017-01-05
You have to specify a correct datatype for the parameter. Date and DateTime works, Date and String not.
Correct this one:
new SqlParams("#CrashTime", SqlDbType.Date, dateTimePicker1.Value.Date.ToString("yyyy-MM-dd")),
Try this:
new SqlParams("#CrashTime", SqlDbType.Date, dateTimePicker1.Value.Date),
The datatype "Date" used in SQL Server accepts "DateTime" variables from your Visual Studio project.

Problems with sending DateTime to SQL Table

I'm writing WinForms code in C# and basically have the following:
DateTime localDate = DateTime.UtcNow;
SqlConnection Conn = new SqlConnection("....[connection info]....");
Conn.Open();
SqlCommand sqlcomm = new SqlCommand("INSERT INTO dbo.Call VALUES(...., #Time,...);", Conn);
sqlcomm.Parameters.Add("#Time", SqlDbType.DateTime);
sqlcomm.Parameters["#Time"].Value = localDate;
Int32 o = sqlcomm.ExecuteNonQuery();
This throws an error of "When converting a string to DateTime, parse the string to take the date before putting each variable into the DateTime object." From what I gather, it thinks the localDate variable is a string but if I write to the console localDate.GetType() it says System.DateTime.
The column for "#Time" in the database is set up to DateTime, so that's not the issue. Any thoughts?
You're almost there. for Sql Server think among these lines
select cast(getdate() as time)
Problem is that in .net there is no such type as time, so you need to adapt
SqlCommand sqlcomm = new SqlCommand(
"INSERT INTO dbo.Call VALUES(...., cast(#Time as time),...);", Conn);
sqlcomm.Parameters.AddWithValue("#Time", localDate);
this is all you should need. Although, I think, you may not even need to add cast as DB engine itself will try cast it. The problem, I think, that you explicitly said your type SqlDbType.DateTime. But if you use AddWithValue, provider will do things for you.
since #Frédéric mentioned TimeSpan, you can try this as well
sqlcomm.Parameters.AddWithValue("#Time", localDate.TimeOfDay);
' and no cast(#Time as time)
The UTC format is not an sql date time format whuch you specified in the parameters.add
In the past I have formatted the utc time to that of yyyy-MM-dd.
Given this table schema:
create table dbo.call_history
(
id int not null identity(1,1) primary key clustered ,
my_date date null ,
my_time time null ,
my_datetime datetime null ,
)
This code works just fine:
using ( SqlConnection conn = new SqlConnection( connectString ) )
using ( SqlCommand cmd = conn.CreateCommand() )
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = #"
insert dbo.call_history ( my_date , my_time , my_datetime )
values ( #pDate , #pDate , #pDate )
select scope_identity()
";
cmd.Parameters.AddWithValue( "#pDate" , DateTime.UtcNow );
conn.Open();
// double downcast required herebecause scope_identity()
// returns numeric(38,0) which gets mapped to decimal
int id = (int)(decimal) cmd.ExecuteScalar() ;
conn.Close();
}

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.

compare DateTime in SqlCommand

I have a simple SqlCommand in which I want to return all records within a specified DateTime range. (both Date and Time are involved)
var dataReader = new SqlCommand(
#"Select RecordID from RecordTable
where RecordTable.WorkingDT between '"+ _startDt +"' and '"+ _endDt +"'",
_sqlConnection).ExecuteReader();
how do I have to set the values for _startDt and _endDt?
You can try this:
var dataReader = new SqlCommand(
#"Select RecordID from RecordTable
where RecordTable.WorkingDT between '"+ _startDt.ToString("yyyy-MM-dd HH:mm:ss") +"' and '"+ _endDt.ToString("yyyy-MM-dd HH:mm:ss") +"'",
_sqlConnection).ExecuteReader();
Where _startDt and _endDt are type of DateTime.
If you add them as proper parameters in your command, you don't need to worry about formatting. The added benefit of getting into the habit of using these is that you don't have to worry about SQL injection when you were to supply strings as parameters.
Have a look at http://www.csharp-station.com/Tutorial/AdoDotNet/lesson06
It shows how to use parameters in your queries. I don't think it needs to be spelled out completely.
An example (copy/pasted from the site):
// 1. declare command object with parameter
SqlCommand cmd = new SqlCommand(
"select * from Customers where city = #City", conn);
// 2. define parameters used in command object
SqlParameter param = new SqlParameter();
param.ParameterName = "#City";
param.Value = inputCity;
// 3. add new parameter to command object
cmd.Parameters.Add(param);
// get data stream
reader = cmd.ExecuteReader();
And yes, defining the parameters can be done shorter that 3 lines per parameter. But that's left up to the reader.
#kmatyaszek, While commonly used, the "yyyy-mm-dd HH:mm:ss" date format is not guaranteed to be unambiguously parsed by SQL server. If you must create SQL from concatenating strings (not necessary in this case as René has shown) then you should use the ISO8601 format, which is just the same but with a T in the middle: "yyyy-mm-ddTHH:mm:ss".
http://msdn.microsoft.com/en-us/library/ms190977%28v=sql.90%29.aspx
"The advantage in using the ISO 8601 format is that it is an
international standard. Also, datetime values that are specified by
using this format are unambiguous. Also, this format is not affected
by the SET DATEFORMAT or SET LANGUAGE settings."
For a demonstration why, try this rerunnable Sql script.
if object_id('tempdb..#Foo') is not null drop table #Foo;
create table #Foo(id int, d datetime)
-- Intend dates to be 12th Jan.
set dateformat ymd
insert into #Foo(id, d) values (1, '2012-01-12 01:23:45') -- ok
insert into #Foo(id, d) values (2, '2012-01-12T01:23:45') -- ok
set dateformat ydm
insert into #Foo(id, d) values (3, '2012-01-12 01:23:45') -- wrong!
insert into #Foo(id, d) values (4, '2012-01-12T01:23:45') -- ok
select * from #Foo order by id
if object_id('tempdb..#Foo') is not null drop table #Foo;

Categories