Retrieving Database procedure value with Provider - c#

I am trying to retrieve data from my database procedure but I'm not sure why I'm getting a return value of -1 when a value of 1 or 0 is supposed to be returned. I feel as thought everything is being passed in correctly and the procedure is running well. But I could be wrong.
I pass an object with the name of "Status" of type int into my database procedure db.proc_CsStatus and db.proc_GhStatus. During the debugger though I get "r" a value of -1.
My Controller:
public ActionResult Index()
{
ViewBag.CsStatus = GhCsStatusProvider.GetCsStatus();
ViewBag.GhStatus = GhCsStatusProvider.GetGhStatus();
return View();
}
My provider has these two functions:
public static int GetGhStatus()
{
using (Entities db = new Entities())
{
System.Data.Objects.ObjectParameter s = new System.Data.Objects.ObjectParameter("Status", typeof(int));
int r = db.proc_CsStatus(120, s);
return r;
}
}
public static int GetCsStatus()
{
using (Entities db = new Entities())
{
System.Data.Objects.ObjectParameter s = new System.Data.Objects.ObjectParameter("Status", typeof(int));
int r = db.proc_CsStatus(120, s);
return r;
}
}
Here are my database procedures:
For proc_GhStatus
USE [DATABASE_GH]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[proc_GhStatus]
-- Add the parameters for the stored procedure here
#TimeLimit Int,
#Status Int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Declare variables.
DECLARE #LastUpdate Int
-- Calculate the LastUpdate.
SELECT #LastUpdate = DATEDIFF(second, Timestamp, CURRENT_TIMESTAMP)
FROM Heartbeat
WHERE Id=2
-- Compare it to the TimeLimit.
IF #LastUpdate > #TimeLimit SELECT #Status = 0
ELSE SELECT #Status = 1
END
GO
For CsStatus
USE [DATABASE_CS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[proc_CsStatus]
-- Add the parameters for the stored procedure here
#TimeLimit Int,
#Status Int OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Declare variables.
DECLARE #LastUpdate Int
-- Calculate the LastUpdate.
SELECT #LastUpdate = DATEDIFF(second, Timestamp, CURRENT_TIMESTAMP)
FROM Heartbeat
WHERE Id=1
-- Compare it to the TimeLimit.
IF #LastUpdate > #TimeLimit SELECT #Status = 0
ELSE SELECT #Status = 1
END
GO

In the stored procedure you are not return the status. Therefore you can't set the status in the code like below.
int r = db.proc_CsStatus(120, s);
This will only return the status of the stored procedure execution. -1 means there were some errors in stored procedure execution. Simplest way would be remove the out parameter and return the #status from sp. Then you should be able to retrieve the values the way you have done.
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
-- Declare variables.
DECLARE #LastUpdate Int
-- Calculate the LastUpdate.
SELECT #LastUpdate = DATEDIFF(second, Timestamp, CURRENT_TIMESTAMP)
FROM Heartbeat
WHERE Id=1
-- Compare it to the TimeLimit.
IF #LastUpdate > #TimeLimit SELECT #Status = 0
ELSE SELECT #Status = 1
// Below line shoud be added.
RETURN #Status
Also make sure to set right return type in the DBModel as mentioned in other answers.

The possible problem is that the imported SP in EF is not told to return a value. To check do the followings:
Open the .edmx file.
Open Model Browser.
Brows to DBModel.
Under Function Imports section find your SP and right click on it then open Properties.
Check whether the Return Type is set to None or not.
If it is not change it to appropriate value.

Related

User defined type from stored procedure not detected in LINQ

I have created this stored procedure:
CREATE PROCEDURE [dbo].[zsp_MoveItemsToFolder]
(#IdListToMove IdListToMove READONLY,
#FolderId INT,
#UserId INT)
AS
BEGIN
DECLARE #Rowcount INT = 1;
WHILE (#Rowcount > 0)
UPDATE TOP (5000) dbo.SingleScannedItems --<-- define Batch Size in TOP Clause
SET MyListId = #FolderId
WHERE SingleScannedItemId IN (SELECT l.SingleScannedItemIds
FROM #IdListToMove l)
AND UserId = #UserId
SET #Rowcount = ##ROWCOUNT;
CHECKPOINT; --<-- to commit the changes with each batch
END
Prior to that I have created a user defined type in SQL like this:
CREATE TYPE [dbo].[IdListToMove] AS TABLE(
[SingleScannedItemIds] int NULL
);
And once I have imported the procedure into the C# LINQ the only parameters that I can see are FolderId and UserId.
However the #IdListToMove user defined type is not visible in the imported stored procedure :/...
So my question is: why is the user defined type not visible in the imported stored procedure (that is imported through the Entity Framework 6)
How do I fix this so that I can pass the list through C# into the stored procedure?
Can someone help me out?
Edit: here's the modified procedure with #Marc Gravel's suggestions:
ALTER PROCEDURE [dbo].[zsp_MoveItemsToFolder]
(#IdListToMove NVARCHAR(MAX),
#FolderId INT,
#UserId INT)
AS
BEGIN
DECLARE #Rowcount INT = 1;
WHILE (#Rowcount > 0)
UPDATE TOP (5000) dbo.SingleScannedItems --<-- define Batch Size in TOP Clause
SET MyListId = #FolderId
WHERE (EXISTS (SELECT 1
FROM dbo.SplitStringProduction(#IdListToMove,',') S1
WHERE SingleScannedItemId = S1.val))
AND UserId = #UserId
AND MyListId <> #FolderId
SET #Rowcount = ##ROWCOUNT;
CHECKPOINT; --<-- to commit the changes with each batch
END

Why I get exception when I call stored procedure?

I am using Entity Framework 6 and Microsoft SQL Server 2012.
Here is my stored procedure:
ALTER PROCEDURE SPDeleteRegion
#siteId int,
#regionId int
AS
BEGIN
SET NOCOUNT ON;
DECLARE #isDeleted BIT
IF EXISTS (SELECT 1 FROM SiteObjects WHERE SiteRegionId = #regionId)
BEGIN
SET #isDeleted = 0 ; --not deleted
RETURN #isDeleted;
END
ELSE
BEGIN
--do what needs to be done if not
DELETE FROM SiteRegions
WHERE Id = #regionId;
SET #isDeleted = 1; -- deleted
RETURN #isDeleted;
END
END
Here how I call the stored procedure in C#:
var t = _context.Database.SqlQuery<bool>("SPDeleteRegion #siteId, #regionId",
new SqlParameter("#siteId", siteId),
new SqlParameter("#regionId", regionId));
On the line of code above I get this exception:
The data reader has more than one field. Multiple fields are not valid for EDM primitive or enumeration types.
Any idea why I get the excewption and how to fix it?
Your procedure doesn't selecting anything. Change it like this:
ALTER PROCEDURE SPDeleteRegion
-- Add the parameters for the stored procedure here
#siteId int,
#regionId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#isDeleted BIT
IF EXISTS (SELECT 1 FROM SiteObjects WHERE SiteRegionId = #regionId)
BEGIN
SET #isDeleted = 0 ; --not deleted
SELECT #isDeleted [IsDeleted]; --HERE
END
ELSE
BEGIN
--do what needs to be done if not
DELETE FROM SiteRegions WHERE Id = #regionId;
SET #isDeleted = 1;--deleted
SELECT #isDeleted [IsDeleted]; -- AND HERE
END
END

ADO.NET stored procedure for inserting not working

I have a database which stores information about a library (books, authors & categories).
But I can't get my stored procedure to work for inserting data. The stored procedure itself executes fine, but when I perform a test, it simply doesn't add anything to the database. Can anyone see what I'm missing?
This is my stored procedure (for category):
USE MyLibrary
GO
IF EXISTS (SELECT 1 FROM sysobjects WHERE name = 'CategoryInsert' AND TYPE = 'P')
BEGIN
DROP PROC CategoryInsert
END
GO
CREATE PROCEDURE CategoryInsert
(
#Id int out,
#Name nvarchar(255),
#InsertedBy nvarchar(120),
#InsertedOn datetime
)
AS
DECLARE #CurrentId int
SELECT #CurrentId = Id FROM Category WHERE lower(#Name) = lower(#Name)
IF #CurrentId IS NOT NULL
BEGIN
SET #Id = -100
RETURN
END
INSERT INTO Category
(
Name,
InsertedBy,
InsertedOn
)
VALUES
(
#Name,
#InsertedBy,
#InsertedOn
)
SET #Id = SCOPE_IDENTITY()
GO
This is my test:
USE MyLibrary
GO
DECLARE #NewId int
DECLARE #date datetime
SET #date = getdate()
EXEC CategoryInsert #NewId, 'Testing', 'AL', #date
SELECT #NewId
GO
This line:
SELECT #CurrentId = Id FROM Category WHERE lower(#Name) = lower(#Name)
IF #CurrentId IS NOT NULL
The equality check will always return true because you're essentially comparing WHERE 1 = 1, which means that #CurrentID will always have a value and thus your stored procedure will always return before the INSERT happens.

Passing value from int as output parameter to a int Variable using LINQ in c#

I have a stored Procedure as
ALTER PROCEDURE [dbo].[customers_iu] (#intId as int, #strName as nvarchar(100), #strSname as nvarchar(100),#intInsupdt as int = 0, #intGnrtdid as int OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
if #intInsupdt = 1
begin
insert into dbo.customers (cust_Name, cust_Sname, cust_Tinno) values (#strName, #strSname,#strTinno)
set #intGnrtdid = (select ident_Current('dbo.customers'))
end
else if #intInsupdt = 0
begin
update dbo.customers set cust_Name = #strName, cust_Tinno = #strTinno where cust_Id = #intId ;
set #intGnrtdid = #intId
end
END
I want to get #intGnrtdid value to a int Variable in using LINQ.
See Scott Guthrie's excellent blog series on Linq to SQL. Part 6 covers calling stored procedures. An out parameter would simply be represented by a ref parameter when calling your strongly typed stored procedure from code.

Get value output from SQL Server stored procedure into variable

This seems to be a simple question but nevertheless I haven't found an answer yet.
I have the following stored procedure
CREATE PROCEDURE [dbo].[AllocateId]
AS
BEGIN TRANSACTION
UPDATE TOP(1) IdReservation
SET IsAllocated = 1
OUTPUT DELETED.Id
WHERE IsAllocated = 0
COMMIT TRANSACTION
GO
It's been used in C# + EF code without a problem via ExecuteFunction of ObjectContext
ObjectResult<int> objectResult = ExecuteFunction<int>("AllocateId");
However when I try to call it directly from SQL script it doesn't seem to work
declare #Id int
EXEC #Id = [dbo].[AllocateId]
#Id is always 0. How do I get the value into #Id variable in sql script?
Procedure return value is different from result set(s) returned by that procedure. Your stored procedure returns a result set and does not return a return value (which ends up being null, which gets converted to 0 implicitly upon exiting the procedure).
To get the resultset your existing procedure retuns, you need insert ... exec:
declare #t table (id int);
insert into #t
exec [dbo].[AllocateId];
If you want to return a value as a return value as well, you should amend you stored procedure:
CREATE PROCEDURE [dbo].[AllocateId]
AS
BEGIN TRANSACTION
declare #id int;
UPDATE TOP(1) IdReservation
SET #id = Id, IsAllocated = 1
OUTPUT DELETED.Id
WHERE IsAllocated = 0
COMMIT TRANSACTION
return #id;
Then it will work in the way you describe in the question.

Categories

Resources