EntityFramework and sp_executesql - sql

Why when running the following auto-generated SQL from Entity Framework ObjectContext.ExecuteStoreCommand(), the parameters all result in NULL.
exec sp_executesql
N'SaveModel',
N'#ModelID int,#Name nvarchar(24),#Description nvarchar(34)',
#ModelID=4,
#Name=N'Status',
#Description=N'The status of a model.'
I've taken this SQL from Profiler after the ExecuteStoreCommand runs, as you can see the #ModelID param is being set to 4, Name = 'Status', Description = 'The status of the model'. However, when doing a print of ModelID in the stored procedure SaveModel, it is NULL. Here is the stored procedure demonstrating the null parameters:
USE [Bluewater]
GO
/****** Object: StoredProcedure [dbo].[SaveModel] Script Date: 08/09/2011 13:15:04 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Nicholas Barger
-- Create date: 08/07/2011
-- Description: Save model entity (create/update).
-- =============================================
ALTER PROCEDURE [dbo].[SaveModel]
#ModelID int = null,
#Name varchar(255) = null,
#Description varchar(1000) = null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
PRINT ('ModelID: ' + CAST(ISNULL(#ModelID, 0) AS VARCHAR(10)));
END
-- POST ANSWER --
The problem was the original call using ExecuteStoreCommand(), I thought the first parameter requested only the name of the stored procedure, not the full stored procedure syntax. Here is an example of BROKEN code:
e.ExecuteStoreCommand("SaveModel", new SqlParameter[] {
new SqlParameter("ModelID", model.ModelID),
new SqlParameter("Name", model.Name),
new SqlParameter("Description", model.Description)
})
And here is the WORKING code:
e.ExecuteStoreCommand("SaveModel #ModelID, #Name, #Description", new SqlParameter[] {
new SqlParameter("ModelID", model.ModelID),
new SqlParameter("Name", model.Name),
new SqlParameter("Description", model.Description)
})

The sql that is generated there is not correct, the following sql yields the result you are expecting...
exec sp_executesql
N'SaveModel #ModelID, #Name, #Description',
N'#ModelID int,#Name varchar(24),#Description varchar(34)',
#ModelID=4,
#Name=N'Status',
#Description=N'The status of a model.'
Looks to me like this is either
A) A bug in Entity Framework
B) A problem with your Entity Model

Related

Update stored procedure using C#?

I have 10 database servers and most procedures are the same.
So I plan to make procedure distribute program.
For convenient application, I want to use "the procedure modify code made by tool" itself.
For example, when I click modify button of the procedure on SSMS the code is like below.
USE [DB]
GO
/****** Object: StoredProcedure [dbo].[HongTestProcedure] Script Date: 2020-08-28 오전 11:09:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: hong
-- Create date: 2020-03-07
-- =============================================
ALTER PROCEDURE [dbo].[HongTestProcedure]
-- Add the parameters for the stored procedure here
#ID varchar(10)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT *
FROM table
END
And then, if I want to modify the parameter of the procedure.
Maybe the code is like below:
USE [DB]
GO
/****** Object: StoredProcedure [dbo].[HongTestProcedure] Script Date: 2020-08-28 오전 11:09:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: hong
-- Create date: 2020-03-07
-- =============================================
ALTER PROCEDURE [dbo].[HongTestProcedure]
-- Add the parameters for the stored procedure here
#ID varchar(10)
#ID2 varchar(10) -- it is added.
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT *
FROM table
END
I consider that program has a textbox and button.
and I want to insert all above code.
maybe it looks like it:
So, I try the code like below:
public bool UpdateProcedure(string dbip, string query)
{
DataSet ds = new DataSet();
SqlConnection sqlConn = new SqlConnection("server = " + dbip + dbInfo);
sqlConn.Open();
SqlCommand sqlComm = new SqlCommand(query, sqlConn);
sqlComm.ExecuteNonQuery();
return true;
}
If it run successfully, I will run query on 10 database servers.
But it return error message. even it can be run in SSMS.
incorrect syntax near 'GO'
CREATE/ALTER PROCEDURE must be the first statement in a query batch
Can I solve it?
Yes. Since you can construct it as an Dynamic SQL in C# and Open an SQL Connection and pass the Dynamic SQL to EXEC sp_executesql #DynamicSQL. This will create the required SP in the required Database.

Unable to pull out resetSet for insert within stored procedure

I have been looking online for a few days to find a solution and
I may be asking the wrong questions.
I have the following stored proc which on insertion of a row to a db I want to get back the output int (#outResult). This is the stored proc :
USE [DB1]
GO
/****** Object: StoredProcedure [dbo].[storedProc1] Script Date: 04/12/2016 10:16:23 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[storedProc1]
-- Add the parameters for the stored procedure here
#inParam nvarchar(max),
#outResult int = 0 OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF NOT EXISTS
(
SELECT ID
FROM dbo.table1
WHERE Field1 = #inParam
)
Insert into [DB1].[dbo].[table1]
(
Field1
)
Values (
#inParam
)
SET #outResult = SCOPE_IDENTITY()
END
When I run the following SQL and try to retrieve the resultSet :
SELECT * FROM (EXEC storedProc1 'field1')
I get the following error:
"Incorrect syntax near the keyword 'exec'"
Maybe I am approaching this problem wrong from the first place?
I will continue to look into this and provide a solution if I find one.Any ideas?
To get the value of the output parameter you need to supply the call to the SP with an output argument. You do that by specifying the OUTPUT option on the second parameter.
DECLARE #returned_ID INT;
EXEC storedProc1 #inParam = 'field1',
#outResult = #returned_ID OUTPUT
SELECT #returned_ID
If you want to retrieve just the out parameter, then You can read it as :
DECLARE #output int
EXEC storedProc1 'field1',#output OUTPUT
SELECT #output

unqiueidenfitier is not compatible with type int SQL Server Procedure

I have the following procedure for inserting into a user table:
-- ================================================
-- Template generated from Template Explorer using:
-- Create Procedure (New Menu).SQL
--
-- Use the Specify Values for Template Parameters
-- command (Ctrl-Shift-M) to fill in the parameter
-- values below.
--
-- This block of comments will not be included in
-- the definition of the procedure.
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Andy Armstrong
-- Create date:
-- Description:
-- =============================================
CREATE PROCEDURE db_SignupAddLogin
-- Add the parameters for the stored procedure here
#LoginName VARCHAR(15),
#LoginPassword VARCHAR(15)
AS
BEGIN
DECLARE #GUID UNIQUEIDENTIFIER
SET #GUID = NEWID();
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO tblMemberLogin
(
UserID,
LoginName,
LoginPassword
)
VALUES
(
#GUID,
#LoginName,
#LoginPassword
)
RETURN #GUID
END
GO
However when I execute it I get the following error:
Msg 206, Level 16, State 2, Procedure db_SignupAddLogin, Line 34
Operand type clash: uniqueidentifier is incompatible with int
I cannot quite workout why as i am not referencing an int anywhere.
My Schema for tblMemberLogin looks like this:
UserID(PK,uniqueidentifier,notnull)
LoginName(nchar(15),not null)
LoginPassword(nchar(15),not null)
Please help!
RETURN can only be used with an int. You can simply use a SELECT query to retrieve the value of variable #GUID.
Reference: http://technet.microsoft.com/en-us/library/ms174998(v=sql.110).aspx
get rid of RETURN #GUID and you should be good to go.
In SQL Server, stored procedures may only return integer values. SQL Server RETURN
If you want to return data from a stored procedure other than an integer, you can use an output parameter: Returning Data from Stored Procedures
You declare the output parameter along with your input parameters:
CREATE PROCEDURE CREATE PROCEDURE db_SignupAddLogin
-- Add the parameters for the stored procedure here
#LoginName VARCHAR(15),
#LoginPassword VARCHAR(15),
#NewGuid UNIQUEIDENTIFIER OUTPUT
AS
BEGIN
SET #NewGuid = NEWID();
-- rest of procedure
END
And then use the output parameter:
DECLARE #NewLoginGuidFromSP UNIQUEIDENTIFIER
EXECUTE db_SignupAddLogin 'Username', 'password', #NewGuid = #NewLoginGuidFromSP OUTPUT;

Maximum stored procedure, function, trigger, or view nesting level exceeded in Visual Studio (ado.net) but not in SQL server

I have a problem with a recursive SQL function. The original problem is that I've got a list of employees, each of them has various trainings. Each of these trainings has some pre requirements. For example to have your Class 1 drivers license you must have your Class 5. If I remove the Class 5 I need to check disable the Class 1.
Now as this is a tree with no fixed max depth (actually I stop checking at 10ish) I decided to use recursion. I wrote two stored procedures
[dbo].[spCheckTrainingPreqs]
#PIN int,
#training_id int,
#missingTraining int OUTPUT
and
[dbo].[spCheckTrainingPreqsEmployee]
#PIN int
Now when I call spCheckTrainingPreqsEmployee with an employee number it creates a cursor for each pin/training_id combo and calls spCheckTrainingPreqs. spCheckTrainingPreqs uses a recursive local cursor to walk the tree.
Now the kicker. It works fine in visual studio
DECLARE #return_value int
EXEC #return_value = [dbo].[spCheckTrainingPreqsEmployee]
#PIN = 12673
SELECT 'Return Value' = #return_value
GO
But if I go into visual studio and add it to a table adapter as a stored proc with no return I get the error "Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)"
I've checked that none of my tables have triggers. The only complexity is that many of the tables have views based off of them with sub queries and even a c# coded custom concatenation function. Remember running it from SQL manager works fine.
Full code for reference
/****** Object: StoredProcedure [dbo].[spCheckTrainingPreqs] Script Date: 08/31/2010 10:13:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[spCheckTrainingPreqs]
#PIN int,
#training_id int,
#missingTraining int OUTPUT
AS
-- get the Prerequisites
declare #requiresID int
declare CurPrereqs cursor local for SELECT RequiresID FROM TrainingPrerequisites WHERE SourceID = #training_id
SET #missingTraining = 0
OPEN CurPrereqs
FETCH NEXT FROM CurPrereqs INTO #requiresID
WHILE ##FETCH_STATUS = 0
BEGIN
IF (#missingTraining = 0) -- stop when a missing training is found
BEGIN
IF (SELECT count(training_id) FROM employee_training WHERE PIN = #PIN AND training_id = #requiresID GROUP BY training_id) = 1
BEGIN
--they have the training
IF (##NESTLEVEL < 10) -- we only check 10 levels deep
BEGIN
EXEC spCheckTrainingPreqs #PIN, #requiresID, #missingTraining
UPDATE employee_training SET missingPreReq = #missingTraining WHERE training_id = #training_id and PIN = #PIN;
END
END
ELSE
BEGIN
SET #missingTraining = #requiresID
UPDATE employee_training SET missingPreReq = #missingTraining WHERE training_id = #training_id and PIN = #PIN;
CLOSE CurPrereqs
DEALLOCATE CurPrereqs;
RETURN
END
END
FETCH NEXT FROM CurPrereqs INTO #requiresID
END
CLOSE CurPrereqs
DEALLOCATE CurPrereqs;
and
/****** Object: StoredProcedure [dbo].[spCheckTrainingPreqsEmployee] Script Date: 08/31/2010 10:28:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Create date: 08/31/2010
-- Description: Checks all pre reqs for an employee
-- =============================================
ALTER PROCEDURE [dbo].[spCheckTrainingPreqsEmployee]
#PIN int
AS
BEGIN
SET NOCOUNT ON;
declare #training_id int
declare #missingTraining int
SET #missingTraining = 0
declare CurPrereqsE cursor local for SELECT training_id FROM employee_training WHERE PIN = #PIN
OPEN CurPrereqsE
FETCH NEXT FROM CurPrereqsE INTO #training_id
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC spCheckTrainingPreqs #PIN, #training_id, #missingTraining
FETCH NEXT FROM CurPrereqsE INTO #training_id
END
CLOSE CurPrereqsE
DEALLOCATE CurPrereqsE;
END
When you say:
Remember running it from SQL manager works fine
what values are you using for the parameters to test? The error in VS is probably caused by a call by the designer. It's worth checking that you are calling the procedure with the same parameters as the designer is using.
Try using SQL Profiler to trace SQL calls and check exactly what values VS is passing. You can then execute the exact same query from within SQL manager. My guess is that you'll get exactly the same result.

Stored procedure parses correctly but will not execute. Invalid object name. Msg 208

I've scripted up a stored procedure as follows. It will parse without errors, but when I try to execute it, it will fail. The error message reads: Msg 208, Level 16, State 6, Procedure aspnet_updateUser, Line 23
Invalid object name 'dbo.aspnet_updateUser'.
Here is the stored procedure.
USE [PMRS2]
GO
/****** Object: StoredProcedure [dbo].[aspnet_updateUser] Script Date: 05/25/2009 15:29:47 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[aspnet_updateUser]
-- Add the parameters for the stored procedure here
#UserName nvarchar(50),
#Email nvarchar(50),
#FName nvarchar(50),
#LName nvarchar(50),
#ActiveFlag bit,
#GroupId int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE dbo.aspnet_Users
SET UserName = #UserName, LoweredUserName = LOWER(#UserName), Email = #Email, FName = #FName, LName = #LName, ActiveFlag = #ActiveFlag, GroupId = #GroupId
WHERE LoweredUserName = LOWER(#UserName)
END
Looks like it might not exist yet, swap the Alter to a Create.
To avoid this happening in the furture, do what we do, never use alter proc. Instead we check for the existance of the proc and drop it if it exists, then create it with the new code:
IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'myProc')
BEGIN
DROP Procedure myProc
END
GO
CREATE PROCEDURE myProc
(add the rest of the proc here)
Here is another solution
USE [PMRS2]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.YourProcedureName', 'P' ) IS NOT NULL
DROP PROCEDURE dbo.YourProcedureName;
GO
CREATE PROCEDURE [dbo].[YourProcedureName] (
#UserName varchar(50),
#Password varchar(50))
AS
BEGIN
SET NOCOUNT ON;
select ... (your query)
END