Stored procedure expects parameter that is being passed - sql

From the following code I get the error that #StartDate is not supplied, however stepping through the two date range parameters have a valid value:
SqlParameter[] ps = new SqlParameter[]
{
new SqlParameter("#StartDate", startDate),
new SqlParameter("#EndDate", endDate)
};
List<AttendanceReportViewModel> res = db.Database.SqlQuery<AttendanceReportViewModel>(Local.queries["AttendanceReport"], ps).ToList();
return res;
The stored procedure :
ALTER PROCEDURE [dbo].[GetAttendanceReport]
#StartDate datetime,
#EndDate datetime
AS
BEGIN
SET NOCOUNT ON;
exec [REMOTE_SRV].LWD.dbo.ReportAttendance_sp #StartDate = #StartDate, #EndDate = #EndDate;
END
Everything works fine when I execute the stored procedure in SQL Server Management Studio but doesn't from within the application.

If your Local.queries["AttendanceReport"] looks something like this:
Local.queries["AttendanceReport"] = "yourProc #StartDate, #EndDate"
Then try this:
List<AttendanceReportViewModel> res = db.Database.SqlQuery<AttendanceReportViewModel(
Local.queries["AttendanceReport"],
new SqlParameter("StartDate", startDate),
new SqlParameter("EndDate", endDate)
).ToList();

Related

MVC SignalR TSQL Issue With DateTime

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))

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

Sending datetime value to a stored procedure

I want to send just date to a stored procedure and I wrote this C# code:
string[] pr = { "/" };
string[] s = txtStartDate.Text.Split(pr, StringSplitOptions.None);
term.Start_date = new DateTime(Convert.ToInt32(s[0]), Convert.ToInt32(s[1]), Convert.ToInt32(s[2])).Date;
s = txtEndDate.Text.Split(pr, StringSplitOptions.None);
term.End_date = new DateTime(Convert.ToInt32(s[0]),Convert.ToInt32(s[1]),Convert.ToInt32(s[2])).Date;
and I send it to the stored procedure like this:
public bool AddNewTerm(Term term)
{
SqlParameter[] parameters = new SqlParameter[]
{
new SqlParameter ("#termName",term.TermName),
new SqlParameter ("#start_date",term.Start_date),
new SqlParameter ("#end_date",term.End_date)
};
return SqlDBHelper.ExecuteNonQuery("AddNewTerm", CommandType.StoredProcedure, parameters);
}
but when it goes to the stored procedure say this:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
I see other topic but they cant help me
This is the stored procedure code:
ALTER PROCEDURE dbo.AddNewTerm
(
#termName varchar(50),
#start_date date,
#end_date date
)
AS
insert into term(termName, start_date, end_date)
values(#termName, #start_date, #end_date)
RETURN
Where is the problem?
I find my answer by changing my way
I used PersianCalendar Class and store it varchar.
The error message talks about a lower limit of 1/1/1753, so, supposing that you have parsed correctly your inputs (30/6/1390) the message seems clearly indicate that the two column start_date and end_dateare of type datetimethat has a lower limit of 1/1/1753.
So, to store a date with year less than 1753 you need a datetime2 or date column that have a lower limit of 1/1/0001
Here a quick reference for the two datatypes
There is another problem in your code. You add the parameters to the array without specyfing their SqlDbType and in this way the Date are added as DateTime parameters that of course cannot accept a value below 1/1/1753. A workaround for your specific code could be.
public bool AddNewTerm(Term term)
{
List<SqlParameter> parameters = new List<SqlParameter>()
{
new SqlParameter("#termName",SqlDBType.VarChar, 50) {Value = term.TermName},
new SqlParameter("#start_date",SqlDBType.DateTime2, 0) {Value = term.Start_Date},
new SqlParameter("#end_date",SqlDBType.DateTime2, 0) {Value = term.End_Date},
};
return SqlDBHelper.ExecuteNonQuery("AddNewTerm", CommandType.StoredProcedure, parameters.ToArray());
}

Retrieve value of a table and using the value in stored procedure

I'm beginner in SQL Server 2012; I need to generate a product ID in a stored procedure, I generated part of the ID in C#, that part of ID includes Industrialist ID and I pass this to my stored procedure. In the stored procedure I need the last product of my Industrialist number and save in to as SQL variable on my stored procedure. How can I do this?
There are many ways to pass items between SQL and C#, you could use an output parameter where you will populate the parameter within the stored procedure.
string variableName;
using (var conn = new SqlConnection("**connection string**"))
using (var cmd = new SqlCommand("storedProcedureName", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("inputParameter", inputParameter);
var outputParameter = new SqlParameter(){
ParameterName="ParameterName"
,Direction = ParameterDirection.Output
,SqlDbType = SqlDbType.VarChar
,DbType = DbType.VarChar
};
conn.Open();
try
{
cmd.ExecuteNonQuery();
variableName = string.Format("{0}", outputParameter.Value);
}
catch{}
finally
{
conn.Close();
}
}
You could return the value using something along the lines of RETURN #returnValue in your procedure, or you could return it within a table.
string variableName;
using (var conn = new SqlConnection("**connection string**"))
using (var cmd = new SqlCommand("storedProcedureName", conn))
{
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("inputParameter", inputParameter);
conn.Open();
try
{
using (var dbReader = cmd.ExecuteReader())
{
if (dbReader.Read())
{
variableName = string.Format("{0}", dbReader["ColumnName"]);
}
}
}
catch{}
finally
{
conn.Close();
}
}
A generic example of a stored procedure which might work:
CREATE PROC [dbo].[storedProcedureName]
#InputParameter VARCHAR
,#OutputParameter VARCHAR OUTPUT
AS BEGIN
DECLARE #insertedId INT;
BEGIN TRANSACTION
INSERT INTO TableName (...Column Names...)
VALUES (... Values...)
SET #insertedId = SCOPE_IDENTITY()
COMMIT
SELECT #OutputParameter = ColumnName
FROM TableName
WHERE IdColumnName = #insertedId
END
EDIT: Possibly more relevant:
CREATE PROC [dbo].[storedProcedureName]
#IndustrialistId INT
,#OutputParameter VARCHAR OUTPUT -- This might be an int, but it's unclear what you want
AS BEGIN
DECLARE #productId INT;
SELECT #productId = MAX(ProductId)
FROM Products
WHERE IndustrialistId = #IndustrialistId;
SET #OutputParameter = CONVERT(VARCHAR,#IndustrialistId) + '-' + CONVERT(VARCHAR,#productId)
END
If you were to provide some code it might be easier for someone to give you a more tailored response. None of the above code has been syntax checked etc. so should be considered more pseudo code but hopefully it gives you something to work with.

How to get flat record set back from stored procedure in Dapper.Net

I've got a project running on SQL Server 2005. I have a stored procedure that accepts some input parameters, has 2 output parameters and also returns a result set from a select statement inside.
The data is not intending to be returned back as objects just a simple dto class 'Foo' which does not have a primary key.
I've tried to use Dapper.Net with the below code, but I get as far as the exception error returned
When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id
Code:
var p = new DynamicParameters();
p.Add("#Code", code);
p.Add("#MessageControlId", getMessageControlId);
p.Add("#SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
var result = this.db.Query(sql: "up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
Should I be able to do this with Dapper.Net? Should I calling something else to get a simple resultset back?
As requested, here is a shell of the procedure,
it will set the returnvalues and also return 1 resultset.
CREATE PROCEDURE [dbo].[up_MessageProcessed_get]
#Code varchar(10),
#MessageControlID varchar(22),
#SuccessCode int OUTPUT,
#ErrorDescription varchar(255) OUTPUT
AS
BEGIN
Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
SET #SuccessCode = 0
SET #ErrorDescription = 'Completed successfully'
END
This isn't so much an "answer" as a "needs more context", but: with the code as posted, it works fine (below). I suspect the issue here is specific to something inside the stored procedure - something peculiar it is doing:
public void TestIssue17648290()
{
var p = new DynamicParameters();
int code = 1, getMessageControlId = 2;
p.Add("#Code", code);
p.Add("#MessageControlId", getMessageControlId);
p.Add("#SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("#ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
connection.Execute(#"CREATE PROCEDURE #up_MessageProcessed_get
#Code varchar(10),
#MessageControlID varchar(22),
#SuccessCode int OUTPUT,
#ErrorDescription varchar(255) OUTPUT
AS
BEGIN
Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
SET #SuccessCode = 0
SET #ErrorDescription = 'Completed successfully'
END");
var result = connection.Query(sql: "#up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
var row = result.Single();
((int)row.MessageProcessID).IsEqualTo(2);
((int)row.StartNum).IsEqualTo(38349348);
((int)row.EndNum).IsEqualTo(3874900);
DateTime startDate = row.StartDate, endDate = row.EndDate;
p.Get<int>("SuccessCode").IsEqualTo(0);
p.Get<string>("ErrorDescription").IsEqualTo("Completed successfully");
}
which outputs:
Running TestIssue17648290 - OK!
(which is to say: that works fine)