EF stored procedure returns integer instead of ObjectResult - entity-framework

I have an issue while using a stored procedure in my MVC + EF application. This stored procedure returns 7 columns but when i add this to my edmx file by updating model from database. It returns only int value. I have other stored procedures as well but they return "ObjectResult" but this stored procedure returns only integer. I want to mention that it did not create any complex type.
Please suggest how i can fix this issue

I do not know why this happens but I found a work around.
It looks like that the EF gives back the count of affected rows. So it works well to set NOCOUNT to ON in the stored procedure.
SET NOCOUNT ON
-- Your Code with a returning SELECT
SELECT * FROM MyTable
SET NOCOUNT OFF
After changing the procedure you need to update your Model from your Database.

Related

EntityState in update?

What is the correct approach while updating a record in CFE ?
We are using webapi controllers, based on this link, the client-side is developped thanks to AngularJS.
I am having troubles updating a record that already exists and my code fails with an CodeFluentDuplicateException.
I read here that EntityState shouldn't be changed manually. When I want to update a server version with the client changes, shall I consider:
Taking the server version and then applying changes made by client ?
Ask the client version to Save() ?
Any other approach ?
Thanks for your answer,
CodeFluentDuplicateException means that you are inserting a record that already exists in the database. This occurs when the stored procedure executes an INSERT statement instead of an UPDATE.
CodeFluent Entities don't use the EntityState to choose whether the entity must be created or updated in the database. Depending on your model, it uses the RowVersion property (insert if null; update otherwise). If there are no way to choose, the stored procedure executes an UPDATE and when no rows are updated it inserts the row. For instance:
CREATE PROCEDURE [dbo].[Role_Save]
(
#Role_Id [uniqueidentifier],
#Role_Name [nvarchar] (256),
)
AS
SET NOCOUNT ON
IF(#_rowVersion IS NOT NULL)
BEGIN
UPDATE [Role] SET
[Role].[Role_Name] = #Role_Name
WHERE (([Role].[Role_Id] = #Role_Id) AND ([Role].[_rowVersion] = #_rowVersion))
END
ELSE
BEGIN
INSERT INTO [Role] (
[Role].[Role_Id],
[Role].[Role_Name])
VALUES (
#Role_Id,
#Role_Name)
END
So in your case I would check the code of the generated stored procedure to understand why it tries to insert the record instead of updating it.
In fact you can change the EntityState manually if you need to, but there are only a few reasons to do it.

map stored procedure to entity returning temproray table data

I have a stored procedure that returns the temporary table data. because i have used dynamic queries. When i tried to map stored procedure using complex types it returns no columns
how to handle temporary table columns name in complex types?
It is not supported by default because EF always executes SET FMTONLY ON before executing your stored procedure. This option will turn off logic execution - it will only ask for metadata but if logic execution is turned off no temporary table is created and no column's metadata exists.
There are some workarounds.

Most straightforward way to add a row to an SQL Server table in ADO.NET without hardcoded SQL?

I am wondering what the best / most efficient / common way is to add a row to an SQL Server table using C# and ADO.NET. I know of course that I can just create an SQL statement for that, but first, the destination table schema might vary, so I want to keep this flexible, and second, there are so much columns that I do not want to code and maintain this manually. So I currently use a SqlCommandBuilder that is automatically creating the proper insert statement for me, together with an SQLDataAdapter, like this:
var dataAdapter = new SqlDataAdapter("select * from sometable", _databaseConnection);
new SqlCommandBuilder(dataAdapter);
dataAdapter.Fill(dataTable);
// ... add row to dataTable, fill fields from some external file that
// ... includes column names as well,
//.... add some more field values not from the file, etc. ...
dataAdapter.Update(dataTable);
This seems pretty inefficient though to first grab all the records from the table even though I do not need them for anything (especially considering that there might even already be a million records in there). Using some select statement like select * from sometable where 1=2 would work, but it does not seem like a very clean approach. I imagine there is some different solution for this that I am just not aware of.
Thanks,
Timo
I think the best way to insert rows is by using Stored Procedures through the ADO.NET command object.
If you are inserting massive amounts of data and are using SQL Server 2008 you can pass DataTable objects to a stored procedure by using a User-Defined Table Types.
In SQL:
CREATE TYPE SAMPLE_TABLE_TYPE --
AS
field1 VARCHAR(255)
field2 VARCHAR(255)
CREATE STORED PROCEDURE insert_data
AS
#data Sample_TABLE_TYPE
BEGIN
INSERT INTO table1 (field1, field1)
SELECT username, password FROM #data;
In .NET:
DataTable myTable = new DataTable();
myTable.Columns.Add(new DataColumn("field1", typeof(string));
myTable.Columns.Add(new DataColumn("field1", typeof(string));
SqlCommand command = new SqlCommand(conn, CommandType.StoredProcedure);
command.Parameters.Add("#data", myTable);
command.ExecuteNonQuery();
If you data also contains updates you can use the new MERGE function used in SQL Server 2008 to efficiently perform both inserts and updates in the same procedure.
However, if creating User-Defined Table Types and creating stored procedures is too much work, and you need a complete dynamic solution I would stick with what you have, with the recommendation of using the
Where 1 = 0
appended to your SQL text.
You also can use "SELECT TOP(0) * FROM SOMETABLE;" query.

Problem with Entity Framework 4, Complex Types, StoredProcs, and temp tables

I am skinning my knees on Entity Framework 4 and running into a slight problem.
I have some stored procedures that I am pulling into my EDMX. When I create complex types from these procs, EF has no problem getting the column information. Except in one place. After being puzzled for a while, I figure out it was my temporary table getting populated that is causing the problem. Actually it is simply calling the INSERT into the temp table that is causing the problem. I'm not actually populating it with any information.
While I know that I can manually create a complex type then map the function to that type, I would like to be able to just let EF take care of it for me. Does anyone know what I am doing wrong?
Below is a sample proc that doesn't work. Run this in a DB and add the proc to you EDMX. Then try to get the column information in the "Add Function Import" screen. Nothing is returned. Comment out the INSERT to the temp table and get the column information and it works.
Thanks,
Steve
CREATE PROCEDURE dbo.TestProc
AS
SET NOCOUNT ON
CREATE TABLE #TempTable(
StartDate datetime
)
INSERT INTO #TempTable
SELECT null
DROP TABLE #TempTable
SELECT 1 AS ReturnValue
SET NOCOUNT OFF
GO
A few things to try.
Use Variable Tables instead -> maybe the import wizard prefers that?
Name your return fields.
Try using the following stored proc (untested .. just thinking out loud...)
CREATE PROCEDURE dbo.Foo
AS
SET NOCOUNT ON
DECLARE #ResultTable TABLE (SomeId INTEGER)
INSERT INTO #ResultTable
SELECT DISTINCT Id AS Identity -- Or u can rename this field to anything...
FROM SomeExistingTableWhichHasAnIdentityField
GO
Try that and see if the wizard refreshes, now.
--
Attempt #2 :)
Ok .. when the EF designer/wizard/whatever fails to figure out EXACTLY what my stored proc is suppose to be returning, I usually do the following :-
Make sure the stored procedure doesn't exist at all in the EF designer/context, etc. (You have a clean starting point)
Open up your stored procedure and /* /* comment out EVERYTHING after the procedure definition.
eg..
ALTER PROCEDURE dbo.Foo
(
Bar1 INT,
Bar2 TINYINT,
... // whatever u have as your optional input arguments //
)
AS
SET NOCOUNT ON
/*
.... every thing in here is commented out
*/
GO
Now ...
3. Add a forced fake return in the stored proc, which (more or less) just defines the output structure/fields.
eg..
ALTER PROCEDURE dbo.Foo
(
Bar1 INT,
Bar2 TINYINT,
... // whatever u have as your optional input arguments //
)
AS
SET NOCOUNT ON
SELECT 1 AS Id, 1 AS UserId, 1 AS SomeOtherId,
CAST('AAA' AS NVARCHAR(350)) AS Name,
-- etc etc etc..
/*
.... every thing in here is commented out
*/
GO
and then ...
Add this stored proc to your EF designer/wizard/etc... Now the correct fields should be 'determined' by the designer. AWESOME. Yes .. the values are all hardcoded .. but that's ok (so far).
Once your happy that EF is now updated right, go back to your stored proc, and remove all hardcoded SELECT (which we did in the above step). Now we remove the comments which we commented out the entire real code. So you should have your original stored proc, back.
... and now EF is updated and doesn't know we've changed the plumbing of your stored proc.
win :)
does this work for ya?
Here is a variation of Pure.Krome's excellent answer. Rather than commenting out your sproc code, create a new view that consists of only the "fake" select statement described by Pure. The view will be used to create an entity. The view entity then becomes the container for the stored procedure results.
Create View dbo.FooWrapperView as
Select IsNull(MyPrimaryID,-999) as IntFieldName, --IsNull disallows nulls so EF designer will make this the primary key.
NullIf(CAST('AAA' as VarChar(20)), '') as VarChar20FieldName, --NullIf allows null so EF designer will NOT make this part of the primary key.
NullIf(CAST('AAA' as VarChar(42)), '') as VarChar42FieldName,
NullIf(CAST(1.1 as DECIMAL(8, 5)), '') as Decimal85FieldName
In the entity designer right-click and choose "Update Model From Database" then select your wrapper view (and the sproc if you haven't done so already). This will create the entity mapped to the bogus wrapper view. The designer picks the primary key based on the view's IsNull and NullIf statements (details here). Find the sproc in the model browser. Right-click it and select "Add Function Import...". Under "Returns a collection of" select Entities. Choose your view entity and click OK. Now when your stored procedure is called it will dump the results into your view entity.
MyProject.MyEntities myContext = new MyProject.MyEntities();
var myQuery = myContext.usp_FOO(myRecordID);
FooWrapperViewEntity myFooEntity = new FooWrapperViewEntity();
myFooEntity = myQuery.FirstOrDefault();
At first you have to create a normal store procedure without using temp table. this store procedure will contain all the column name (normal table+temp table). Now will be able to create the complex type in your EDMX
For more see this

Why does my typed dataset not like temporary tables?

I am attempting add a tableadapter to a stored procedure in my SQL Server 2005 Express. The stored procedure, however, uses a temporary table called #temp. When creating the table adapter, Visual Studio complains "Unknown Object '#temp'" and says that the stored procedure returns 0 columns. This is problematic because I use that stored procedure with a crystal report, and need those columns.
How can I fix this?
Bizarre. According to this you add
IF 1=0 BEGIN
SET FMTONLY OFF
END
to the SP right after the AS part of the SP and it works. Visual Studio now has no problem with it. I have no idea why this works like this, or why it would work, but it does.
This may be an old thread and the answer is found, but when someone gets into your stored procedure after and see this code, he really does not understand. There is another way to do this properly and it is to simply declare the table as a variable like this :
DECLARE #temp TABLE
(
SomeText1 nvarchar(255),
SomeText2 nvarchar(255)
)
Also, don't forget to remove the DROP TABLE at the end.
PS : If you really need to use the temporary table because you need to create it, then you have to write the code given in the previous answer. Hope this helps.