MVC SignalR TSQL Issue With DateTime - sql

I'm trying to migrate from ASP.NET WebForms to MVC and have used this example
which worked fine using SQL Server 2008 Express hosted on an Azure VM. However once I modified the SQL from the "Step 6: Get the Data from the Repository" section of the tutorial:
public class MessagesRepository
{
readonly string _connString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
public IEnumerable<Messages> GetAllMessages()
{
var messages = new List<Messages>();
using (var connection = new SqlConnection(_connString))
{
connection.Open();
using (var command = new SqlCommand(#"SELECT [MessageID], [Message], [EmptyMessage], [Date] FROM [dbo].[Messages]", connection))
{
command.Notification = null;
var dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
messages.Add(item: new Messages { MessageID = (int)reader["MessageID"], Message = (string)reader["Message"], EmptyMessage = reader["EmptyMessage"] != DBNull.Value ? (string) reader["EmptyMessage"] : "", MessageDate = Convert.ToDateTime(reader["Date"]) });
}
}
}
return messages;
}
private void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
if (e.Type == SqlNotificationType.Change)
{
MessagesHub.SendMessages();
}
}
}
Which I changed the SQL to this:
#"SELECT [AssignedToUser], [Status], [RequestID] FROM [dbo].[Notifications] WHERE AssignedToUser IS NOT NULL AND Status IS NOT NULL AND RequestID IS NOT NULL AND AssignedToUser = 'Kyle G' AND Status = 'Red'
Which worked fine but when I wanted to get only notifications stamped with today's date and appended my SQL:
AND CAST(TimeStatusChange AS DATE) = CONVERT(date, getdate())
Or even this:
AND TimeStatusChange >= (GetDate() - 1)
It fails to update unless you refresh the page. Any ideas friends?
Note-TimeStatusChange is a datetime field.
I converted the current day and database field "TimeStatusChange" as such:
SELECT convert(varchar(25), TimeStatusChange, 120) AS TimeStatusChange, [Id],[AssignedToUser], [Status], [RequestID] FROM [dbo].[Notifications] WHERE AssignedToUser IS NOT NULL AND Status IS NOT NULL AND RequestID IS NOT NULL AND AssignedToUser = 'Kyle G' AND Status = 'Red' AND convert(varchar(25), getdate(), 112) = convert(varchar(25), TimeStatusChange, 112) ORDER BY TimeStatusChange DESC
It should be noted that the issue remains and is not that the SQL when run VS 2015 or SSMS does not work it does. It also works on a page refresh of the MVC page. It does not push the new record to the page in real time without a page refresh.
Here is the results in SSMS using Convert for both the TimeStatusChange and getdate() objects:
In other words if I do this (Essentially an "If 1==1" test):
SELECT TimeStatusChange FROM [dbo].[Notifications] WHERE convert(varchar(25), TimeStatusChange, 112) = convert(varchar(25), TimeStatusChange, 112)
SignalR Updates the page upon INSERT of new record.
If I change it to compare the DB field to today's date as strings:
SELECT TimeStatusChange FROM [dbo].[Notifications] WHERE convert(varchar(25), TimeStatusChange, 112) = convert(varchar(25), getdate(), 112)
SignalR no longer updates the page on INSERT new record unless I refresh it. The SQL works it just breaks SignalR from updating the page without a refresh.
If I do the opposite If 1==1 test by comparing today's date to itself as a string:
SELECT TimeStatusChange FROM [dbo].[Notifications] WHERE convert(varchar(25), getdate(), 112) = convert(varchar(25), getdate(), 112)
This also breaks SignalR from updating the page UNLESS I refresh the page. The clue seems to be a problem with:
convert(varchar(25), getdate(), 112)
Breaking SignalR, not the SQL. Perhaps this is too difficult to troubleshoot without having the full solution available.

To answer your question " Do you have a suggestion as to how to get today's date as just the date and no time as a date?"
Here is how you would convert the dates:
SELECT CONVERT(VARCHAR(10),GETDATE(),112),CONVERT(VARCHAR(10),GETDATE(),111),CONVERT(VARCHAR(10),GETDATE(),110)
and the results:

I finally got it (Thanks to Kamran & Dan for hints). I do not understand why this worked but by passing the current date into the SQL statement as a string as opposed to using getdate() or DATEADD in SQL made it work! Why is beyond my pay grade.
Here is the working code (yes I will parameterize it!)
string dateof = DateTime.Today.ToString("MM/dd/yyyy");
connection.Open();
using (var command = new SqlCommand(#"SELECT [Id],[AssignedToUser], [Status], [RequestID] FROM [dbo].[Notifications] WHERE '" + dateof + "' = convert(varchar(25), TimeStatusChange, 101) ORDER BY TimeStatusChange DESC", connection))

Related

Error occurs when trying to convert nvarchar to date mssql node js

I'm trying to query a SQL Server from node js, using the mssql module. The date format in the database is dd/mm/yyyy hh:mm:ss. The query works just fine from SQL Server Management Studio, but it generates the following error when used in node.js:
Here is the code:
//This query aims to retrieve the records that have been inserted to the database in the last 5 min
var sq = "SELECT * FROM [ofm1].[dbo].[ass_site] WHERE CONVERT(datetime, date1) > DATEADD(MINUTE, -5, GETDATE());"
conn = new mssql.ConnectionPool(dbConfig);
conn.connect().then(function () {
var request = new mssql.Request(conn);
request.query(sq).then(function (recordSet) {
recordSet = recordSet.recordset;
recordSet = JSON.stringify(recordSet)
recordSet = JSON.parse(recordSet)
recordSet.forEach(function(row) {
console.log("row:nevr: " + row.nevr)
console.log("row:group id " + row.codeass)
var rq = new mssql.Request(conn);
rq.input('id', mssql.NChar, row.nevr)
rq.input('group', mssql.NChar, row.codeass)
rq.input('feedback', mssql.Text, "new ticket !")
rq.input('url', mssql.NChar, "")
rq.input('notified', mssql.TinyInt, 0)
rq.query("INSERT INTO [ofm1].[dbo].[ticket] values (#id, #group, #feedback, #url, #notified);").then(function() {
});
});
/* console.log(recordSet);
console.log("description: " + recordSet.name);*/
// conn.close();
}).catch(function (err) {
console.log(err);
conn.close();
});
}).catch(function (err) {
console.log(err);
});
Any help will be greatly appreciated, many thanks!!!
usually this error happens when trying to convert date not well formatted
for example try to convert date of format mm/dd/yyyy using dd/mm/yyyy format
SELECT CONVERT(datetime, '06/18/2018 12:05:23',103)
result:
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
but if it is well formatted as following will working fine
SELECT CONVERT(datetime, '18/06/2018 12:05:23',103)
result:
2018-06-18 12:05:23.000
specify format code of your date to be 103 to match your date format dd/mm/yyyy as following:
//This query aims to retrieve the records that have been inserted to the database in the last 5 min
var sq = "SELECT * FROM [ofm1].[dbo].[ass_site] WHERE CONVERT(datetime, date1,103) > DATEADD(MINUTE, -5, GETDATE());"
for more details about format code check following link

Stored procedure wrong output

I have this stored procedure that returns data on a selected week, as in the Company, Name, Expected Work, and Work done between the 19/10/2015 and the 25/10/2015 (per example).
I have just recently added the Expected Work line and for some odd reason the output differs from one week to another, when the value should be the same.
Company1 - Christopher - 35 - 35 | On one week can give the following on another :
Company1 - Christopher - 350 - 35
I have just realized the value isn't correct when there is a value to Work done, if there is no work recorded the Expected Work has the right value.
Here is the procedure :
ALTER procedure [dbo].[spGetWeeklyActivityByEmployee]
#startDate date
, #endDate date
as
set datefirst 1 -- Monday
select
Company.Name as [Company]
, Employee.FirstName + ' ' + Employee.LastName as [Name]
, sum(UserActivity.Cost) as [Recorder Time]
, sum(Employee.ExpectedTime) as [Expected Time] // I have added this line, not sure if it's correct
from
dbo.Employee
inner join
dbo.Company on Company.CompanyId = Employee.CompanyId
left join
dbo.UserActivity on UserActivity.Login = Employee.Login
and UserActivity.CalendarDate >= #startDate
and UserActivity.CalendarDate <= #endDate
where
(Employee.EntranceDate is null
or YEAR(Employee.EntranceDate) < YEAR(#startDate)
or (YEAR(Employee.EntranceDate) = YEAR(#startDate)
and DATEPART(WEEK, Employee.EntranceDate) <= DATEPART(WEEK, #startDate)))
and (Employee.ExitDate is null
or YEAR(Employee.ExitDate) > YEAR(#endDate)
or (YEAR(Employee.ExitDate) = YEAR(#endDate)
and DATEPART(WEEK, Employee.ExitDate) >= DATEPART(WEEK, #endDate)))
group by
Company.Name, Employee.FirstName + ' ' + Employee.LastName
return 0
Am I missing something? Is the way I retrieve Expected Time wrong?
EDIT :
Here is the part in the code where I save the information in an array :
// create and open a connection object
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
conn.Open();
// 1. create a command object identifying
// the stored procedure
SqlCommand cmd = new SqlCommand("spGetWeeklyActivityByEmployee", conn);
// 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("#startDate", wk1));
cmd.Parameters.Add(new SqlParameter("#endDate", wk2));
// execute the command
rdr = cmd.ExecuteReader();
string[] tab_company = new string[31]; // Don't mind the sizes
string[] tab_name = new string[31];
string[] tab_expectedtime = new string[31];
string[] tab_rectime = new string[31];
int counter;
counter = 0;
while (rdr.Read())
{
tab_company[counter] = rdr["Company"].ToString();
tab_name[counter] = rdr["Name"].ToString();
tab_expectedtime[counter] = rdr["Expected Time"].ToString();
tab_rectime[counter] = rdr["Recorder Time"].ToString();
counter++;
}
Perhaps the change in value comes from here?
Just take away the SUM() from Employee.ExpectedTime and add this to your GROUP BY

Error Date in SQL Query

I have a problem with my SQL query.
The error is :
The conversion of a varchar data type to a smalldatetime data type resulted in an" + " out-of-range value.
I tried to use the CONVERT function to remedy it but in vain.
public static List<string> Helper_Statistic_6(DateTime start, DateTime end) {
DateTime dateStart = start;
DateTime dateEnd = end;
string query = "SELECT ... FROM ... WHERE DATE BETWEEN CONVERT(VARCHAR(10),'" + dateStart+ "',120) and CONVERT(VARCHAR(10),'" + dateEnd+ "',120) ";
}
I suspect you're using C# with Microsoft SQL Server.
In any case, to avoid the woes of code injection, one should try to use parametized SQL. Allow the compiler take care of marshalling a C# Date to a SQL Date.
EDIT: As per #marc_s suggestion, you should beware using reserved SQL keywords as column names, otherwise, protect them from being treated as SQL keywords by using [ ] symbols, i.e. [DATE] isntead of DATE.
I would expect the syntax to look like this:
public static void Run_Helper_Statistic_6(DateTime start, DateTime end)
{
using (SqlCommand command = new SqlCommand(
"SELECT ... FROM ... WHERE [DATE] BETWEEN #start and #end", connection))
{
command.Parameters.Add(new SqlParameter("start", start));
command.Parameters.Add(new SqlParameter("end", end));
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// ...
}
}
}

SQL statement where clause by two dates

I am trying to write a Sql statement which filter the records based on two date variables entered by users. Here is my Sql statement:
public List<DistributionPacking> filterByDeliveryDate()
{
List<DistributionPacking> dateList = new List<DistributionPacking>();
using (var connection = new SqlConnection(FoodBankDB.connectionString)) // get your connection string from the other class here
{
SqlCommand command = new SqlCommand("SELECT d.id, d.packingDate, d.deliveryDate, b.name FROM dbo.Distributions d " +
"INNER JOIN dbo.Beneficiaries b ON d.beneficiary = b.id WHERE d.deliveryDate BETWEEN #fromDate AND #toDate", connection);
command.Parameters.AddWithValue("#fromDate", startDate);
command.Parameters.AddWithValue("#toDate", endDate);
connection.Open();
using (var dr = command.ExecuteReader())
{
while (dr.Read())
{
string id = dr["id"].ToString();
DateTime packingDate = DateTime.Parse(dr["packingDate"].ToString());
DateTime deliveryDate = DateTime.Parse(dr["deliveryDate"].ToString());
string name = dr["name"].ToString();
dateList.Add(new DistributionPacking(id, packingDate, deliveryDate, name));
}
}
}
However, it told me that Conversion failed when converting date and/or time from character string although my data type for packingDate and deliveryDate is DateTime. I wonder why is it so.
Thanks in advance.
Try something like this ...
SELECT d.id, d.packingDate, d.deliveryDate, b.name
FROM dbo.Distributions d INNER JOIN dbo.Beneficiaries b
ON d.beneficiary = b.id
WHERE d.deliveryDate
BETWEEN CAST(#fromDate AS DATETIME) AND CAST(#toDate AS DATETIME)

Variable search query

I have a GridView that will have multiple search options.
Call Date
Start_Time (between two time values)
Call_Time
AgentID
Phone
What they want is all of these options available to search by with a single search button.
What I am having trouble with is how to build the query to be dynamic so if they only search by one option it will search by that, if they search by three of the above it will still provide accurate results.
Here is the Query so far:
SELECT *, 'file://///server/folder/' + replace(call_date, '/', '') + '/'
+ qa_status + '.vox' as url FROM [JM_NSC_Recordings] WHERE ([areacode] + [phone] = #phone)
Phone = [areacode] + [phone] // #phone
Start Time = between [start_time] and [start_time] #starttime
Call Time = [call_time] // #calltime
AgentID = [tsr] // #agentid
Call Date = [call_date] // #calldate
All of these fields in the database are VARCHAR
I used a StringBuilder for same type of advance search in which there are multiple parameters.
StringBuilder stmt=new StringBuilder();
stmt.AppendLine("select * from table where ");
if(phone not blank)
stmt.AppendLine("phone=89754654 and ");
else
stmt.AppendLine("true and ");
if(agentid not blank)
stmt.AppendLine("agentid=89754654 and");
else
stmt.AppendLine("true and ");
else
stmt.AppendLine("true ");
and so on try it will work