Entity Framework shows error when called stored procedure - asp.net

In my project EF calls a stored procedure which is shown below. It returns either 1 or scope identity.
On EF function imports, the stored procedure is listed with a return type of decimal.
When the stored procedure returns scope identity, everything is ok.
But when if condition of sp satisfies, ef throws error as
The data reader returned by the store data provider does not have enough columns for the query requested.
Pls help..
This is my stored procedure:
#VendorId int,
#ueeareaCode varchar(3),
#TuPrfxNo varchar(3),
#jeeSfxNo varchar(4),
#Tjode varchar(3),
#uxNo varchar(3),
#TyufxNo varchar(4),
#Iyuy bit
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
SET NOCOUNT ON;
IF EXISTS (Select dfen_id
from dbo.efe_phfedwn_eflwn
where
[yu] = #Tyuode and
[uy] = #TuyxNo and
[yuno] = #Tuo)
return 1
ELSE
Begin
INSERT INTO dbo.yu
....................
Select Scope_Identity()
End
END

The error tells us that EF is expecting a result set and when we use RETURN we don't get a result set. Your error means that the stored procedure is returning an integer but EF is expecting a decimal, so we just CAST the selected values to a decimal.
So modify the SQL so that we SELECT instead of RETURN, like so (not forgetting to use CAST):
IF EXISTS (Select cntct_ctr_phn_ln_id
from dbo.cntct_ctr_phn_ln
where
[toll_free_phn_area_cd] = #TollfreeareaCode and
[toll_free_phn_prfx_no] = #TollfreePrfxNo and
[toll_free_phn_sfx_no] = #TollfreeSfxNo)
SELECT CAST(1 AS decimal)
Then also CAST the result of SCOPE_IDENTITY() to a decimal:
SELECT CAST(SCOPE_IDENTITY() AS decimal)

Related

Return value to textbox from stored procedure

Having trouble returning the value ID value I need for output back to the textbox in the form. Webforms and ADO.net
I tried adding a param identity as an int and OUT clause, while setting identity = scope_identity and returning the value then using the pattern my team is currently using for ExecuteNonQuery with anonymous parameter classes passing in values and tried passing the #identity value to the textbox.text for the id.
DataManager.Db.ExecuteNonQuery("DefaultConnection", "usp_CreateNewSalesTerritory",
new SqlParameter("#orgId", orgId),
new SqlParameter("#identity", salesTerritoryIdTextBox.Text),
new SqlParameter("#salesTerritoryName", salesTerritories.Name),
new SqlParameter("#createdBy", salesTerritories.CreatedBy),
new SqlParameter("#createdDate", salesTerritories.CreatedDate),
new SqlParameter("#updatedBy", salesTerritories.UpdatedBy),
new SqlParameter("#updatedDate", salesTerritories.UpdatedDate),
new SqlParameter("#isActive", salesTerritories.IsActive));
CREATE PROCEDURE dbo.usp_CreateNewSalesTerritory
#orgId VARCHAR(255),
#salesTerritoryName VARCHAR(255),
#createdBy VARCHAR(255),
#createdDate DATETIME,
#updatedBy VARCHAR(255),
#updatedDate DATETIME,
#isActive BIT,
#identity INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO SalesTerritory (OrganizationId, Name, IsActive,
CreatedBy, CreatedDate, UpdatedBy, UpdatedDate)
VALUES (#orgId, #salesTerritoryName, #isActive,
#createdBy, #createdDate, #updatedBy, #updatedDate);
--SELECT SCOPE_IDENTITY();
--RETURN SCOPE_IDENTITY();
--SELECT ##IDENTITY;
SET #identity = SCOPE_IDENTITY()
END;
RETURN #identity
I expected to get the new inserted ID value for that record, instead, I get the default value of 0 on the screen
Normally, you would call such a stored procedure in "pure" ADO.NET using the .ExecuteNonQuery() method on the SqlCommand object - since it's an INSERT statement.
But now, your stored procedure is actually returning some data - so you really need to treat this like a "normal" SELECT stored procedure.
Assuming you're always returning just the SCOPE_IDENTITY() value - preferably like this:
SELECT SCOPE_IDENTITY();
which is just one single value - you can use the .ExecuteScalar() method on the SqlCommand object - something like this:
object returned = sqlCmd.ExecuteScalar();
if (returned != null)
{
int newIdValue = Convert.ToInt32(returned);
}
// else -> nothing was returned, so most likely no row has been inserted -> handle it appropriately
So maybe you already have a "wrapper" method for .ExecuteScalar() on your DataManager.Db object - or maybe you need to add it. Give it a try - I'm pretty sure this will solve the issue.
I would avoid using the RETURN ... statement - SQL Server stored procedure by default will always return the number of rows that were affected by your stored procedure - don't change that "standard" behavior, if you can.

Can I reuse an INPUT parameter within the stored procedure?

Using SQL Server 2012 within asp.net webforms application, built in VS2012 Express for Web...
In my stored procedure, I have an input parameter #UID_LOGIN AS INT. This value may be ZERO at the time of the call.
CREATE PROCEDURE [dbo].[uspUpdateFromDetailsView]
#UID_CONTACT INT,
#UID_LOGIN INT,
#UID_USER_TYPE INT, -- etc...not shown here...
When this value is ZERO, a new LOGIN record is created and the SCOPE_IDENTITY() is used to fetch the new UID_LOGIN value as follows:
-- Retain the key to the inserted-row.
SET #UID_LOGIN = SCOPE_IDENTITY();
Can I be assured from your answer that this new value of #UID_LOGIN remains local to the stored procedure and does NOT change the value of the parameter.
Thanks in advance... John
Yes, #UID_LOGIN will remain = SCOPE_IDENTITY() within the BATCH until you set it to something else. Each time the procedure is executed you will have to pass in a new #UID_LOGIN because you have not given it a default value in your declaration. i.e. CREATE PROCEDURE [dbo].[uspUpdateFromDetailsView] (#UID_LOGIN = NULL) AS...
You can test snippets like this.
-- Comment out the create procedure part
--CREATE PROCEDURE [dbo].[uspUpdateFromDetailsView]
--( #UID_CONTACT INT,
-- #UID_LOGIN INT,
-- #UID_USER_TYPE INT
--)
--declare your variables
declare #UID_CONTACT INT, #UID_LOGIN INT, #UID_USER_TYPE INT
--set your variable
SET #UID_LOGIN = SCOPE_IDENTITY()
--do some stuff
INSERT INTO TableA (LOGIN) VALUES #UID_LOGIN
--check variable
SELECT #UID_LOGIN

Error in stored procedure with string return type

ALTER PROCEDURE [dbo].[Signin_Check]
#uid varchar(50), #pwd varchar(50), #uname varchar(50) output
AS
IF EXISTS (SELECT * FROM threeLayer_user WHERE uid = #uid and pass = #pwd)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT #uname = name
FROM threeLayer_user
WHERE uid = #uid and pass = #pwd
RETURN #uname
END
This stored procedure is throwing an error :
Conversion failed when converting the varchar value 'Saurav' to data type int.
Your code contains the line
return #uname
the return statement can only accept integer values. However, your #uname parameter is an output parameter, so you do not need to also return it. Just make sure that you specify OUTPUT when calling the sproc:
EXEC dbo.Signin_Check #uid, #password, #uname OUTPUT;
The SP doesn't seem to have bad code related to the error, could you check well the parameters being passed to the stored procedure (i.e. their order and their type)? The problem can be the values that you are passing and not the actual procedure.
Could you append to your post the code you are using when you invoke the stored procedure?
Are you sure that it's varchar column?
#uid varchar(50) / int
uid = #uid

"unsupported parameter" when mapping a stored procedure? (EF)

I have a stored procedure that I return the new ID number. The code looks like this:
ALTER PROCEDURE [dbo]. [Save Contact]
#FirstName varchar (50),
#LastName varchar (50),
#Email varchar (50)
AS
BEGIN
- SET NOCOUNT ON added to Prevent extra result sets from
- Interfering with SELECT statements.
SET NOCOUNT ON;
INSERT INTO Contacts (FirstName, LastName, Email)
VALUES (#FirstName, #LastName, #Email)
SELECT SCOPE_IDENTITY() as newid
END
When I try to map my stored procedures I get the following error:
Error 1 Error 2047: A mapping function binding specifier a function demoModel.Store.SaveContact with an unsupported parameter: id. Output parameters May only be mapped through the RowsAffectedParameter property. Use result bindings to return values ​​from a function invocation.
Is there anyone here who can see what I'm doing wrong?
Need more code, let me know.
With the SQL as it is above remove id as a parameter for the insert statement. Its not needed. To get SCOPE_IDENTITY() you only need to map newid it in the Result Column Bindings.
Also ensure that the column name in Result Column Bindings is the same case as the stored procedure is returning.
Source: http://blogs.msdn.com/b/adonet/archive/2008/03/26/stored-procedure-mapping.aspx

Best way to insert values multiple times from data layer to stored procedure?

Hi
I have DAL Layer, from where invoking a stored procedure to insert values into the table.
E.g.:-
CREATE PROCEDURE [dbo].[DataInsert]
#DataName nvarchar(64)
AS
BEGIN
INSERT INTO
table01 (dataname)
VALUES
(#dataname)
END
Now as requirement changed, per client request i have to add values 5 times. So what is the best practice?
Do i call this Stored Procedure 5 times from my DAL?
or
Pass all the values (may be comma separated) to storedprocedure in one go and then let the stored procedure add it for 5 times?
BTW. Its not always 5 times. It is changeable.
You could create a user-defined table type;
CREATE TYPE [dbo].[SomeInfo] AS TABLE(
[Id] [int] NOT NULL,
[SomeValue] [int] NOT NULL )
Define your stored proc as such;
CREATE PROCEDURE [dbo].[AddSomeStuff]
#theStuff [SomeInfo] READONLY
AS
BEGIN
INSERT INTO SOMETABLE ([...columns...])
SELECT [...columns...] from #theStuff
END
Then you'll need to create a datatable (called table below) that matches the schema and call the stored proc as so;
var cmd = new SqlCommand("AddSomeStuff", sqlConn) {CommandType = CommandType.StoredProcedure};
var param = new SqlParameter("#theStuff", SqlDbType.Structured) {Value = table};
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
btw this proc works - I've just written and tested it see results below!
CREATE PROCEDURE [dbo].[DataInsert]
#DataName nvarchar(max) AS
BEGIN
DECLARE #pos SMALLINT, #str VARCHAR(max)
WHILE #DataName <> ''
BEGIN
SET #pos = CHARINDEX(',', #DataName)
IF #pos>0
BEGIN
SET #str = LEFT(#DataName, #pos-1)
SET #DataName = RIGHT(#DataName, LEN(#DataName)-#pos)
END
ELSE
BEGIN
SET #str = #DataName
SET #DataName = ''
END
INSERT INTO table01 VALUES(CONVERT(VARCHAR(100),#str))
END
END
GO
then run it: -
EXEC #return_value = [dbo].[DataInsert]
#DataName = N'five, bits, of, your, data'
*rows from table01: *
five
bits
of
your
data
(5 row(s) affected)
I'd either call your proc repeatedly(that would be my choice), or else you could use XML to pass in a list of values as a single parameter.
http://support.microsoft.com/kb/555266
Instead of fancy SQL code that is difficult to maintain and is not scalable, I would simply go to invoking your stored procedure multiple times.
If performance or transactional behavior is an issue, you can consider to send the commands in a single batch.
You talked about 5 insert. If the number of record to insert is much greater, you could consider bulk insert as well.

Resources