EntityState in update? - codefluent

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.

Related

EF stored procedure returns integer instead of ObjectResult

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.

How does one call a function from a postgresql rule that has access to NEW and OLD?

I'm new to postgresql (and therefore rules) and I've looked around, but can't really find an example calling a 'global' function.
I am using a normalized database where rows will be flagged as deleted rather than deleted. However, I would like to retain the DELETE FROM... functionality for the end user, by using an instead of delete rule to update the table's deleted_time column. Each table should, therefore, be able to use a common function, but I am not sure how this would be called in this context, or how it would have access to NEW and OLD?
CREATE OR REPLACE RULE rule_tablename_delete AS ON DELETE
TO tablename DO INSTEAD (
/// call function here to update the table's delete_time column
);
Is this even the correct approach? (I note that INSTEAD OF triggers are restricted to views only)
Just use an UPDATE statement:
create rule rule_tablename_delete as
on delete to tablename
do instead
update tablename
set delete_time = current_timestamp
where id = old.id
and delete_time is null;
Assuming that the id column is the primary key of that table.
Some more examples are in the manual: http://www.postgresql.org/docs/9.1/static/rules-update.html

Check referential integrity in stored procedure

I have a customer table and an order table in an sql server 2000 database.
I don't want an order to be in the order table with a customerID that doesn't exist in the customer table so I have put a foreign key constraint on customerID.
This all works fine but when writing a stored procedure that could possibly violate the constraint, is there a way to check whether the constraint will be violated and, if it will be, skip/rollback the query?
At the minute all that happens is the stored procedure returns an error that is displayed on my asp page and looks rather ugly + most users wont understand it.
I would like a more elegant way of handling the error if possible.
Thanks
You have two options:
Add error handling to catch the ugly, error inspect it to see if it's a FK constraint violation and display this to the user. This is IMHO the better solution.
Add code in the stored procedure like the following:
if exists (select null from customer where customerid=#customerId )
begin
--The customer existed so insert order
end
else
begin
--Do something to tell you code to display error message
end
With the second option you will want to watch your transactional consistency. For example what happens if a customer is deleted after your check is made.
You can inspect the data before attempting the operation, or you can attempt the operation and then check the errors after each statement, then ROLLBACK etc.
But you can handle it entirely within stored procedures and return appropriately to the caller according to your design.
Have a look at this article: http://www.sommarskog.se/error-handling-II.html
In SQL Server 2005, there is a possibility of using TRY/CATCH

Using ##identity in a stored procedure good/bad?

I have a stored procedure that inserts a record which has Identity column.
Immediately after inserting I am using ##identity to insert a records in child table.
Are there any implications doing that ?
It's usually not as good as SCOPE_IDENTITY, if your version offers this, because ##Identity isn't limited to the current scope.
It will retrieve the most recent identity even if it was from a different sp in a different table.
Pinal Dave has a straightforward explanation of the IDENTITY offerings here:
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
SCOPE_IDENTITY should be used. If the INSERT should fire a trigger that also performs an identity insert, you'll get the wrong value (i.e., the value generated by the trigger's insert) from ##identity.
##IDENTITY is the last identity value inserted for ANY record. If you get high user concurrency, you're going to end up with the wrong identity value, i.e., you'll get a value which another request just inserted.
For the last identity value inserted in the current scope, use SCOPE_IDENTITY.
Just to add my favoriate artilce on this if for nothing else then for its title "Identity Crisis"

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