2

After trying to work this out for a few hours, I'm beginning to think I can't solve this without your help. Situation:

My stored procudure in SQL Server Management Studio (basically):

SET NOCOUNT ON;
DELETE myTable
...                    -- Complex join query that deletes duplicates
RETURN @@ROWCOUNT      -- The number of rows affected

This procedure works well, if I run it in SSMS the following query is run:

USE myDb
GO
DECLARE @return_value int
EXEC    @return_value = [dbo].[StoredProcedure]
        @var1 = N'asd',
        @var2 = N'fgh',
        @var3 = N'jkl'
SELECT  'Return Value' = @return_value
GO

The result is shown as 1 row with name Return Value and value 8700 (this is correct, it's the number of rows that was deleted by the query).

My problems begin in my C#/NHibernate code. In my NHibernate mapping:

<sql-query name="MyStoredProcedureName">
  exec dbo.StoredProcedure @var1=:var1, @var2=:var2, @var3=:var3
</sql-query>

In my method where I call the stored procedure:

var deletedEntities = session.GetNamedQuery("MyStoredProcedureName")
                             .SetString("var1", "asd")
                             .SetString("var2", "fgh")
                             .SetString("var3", "jkl")
                             .ExecuteUpdate();

This results in deletedEntities = -1. I would like it to be deletedEntities = 8700.

I'd like to point out that the following did return the number of affected rows:

var deletedEntities = session.CreateQuery("DELETE Class c WHERE c.var1 = :var1 AND c.var2 = :var2 AND c.var3 = :var3")
                             .SetString("var1", var1)
                             .SetString("var2", var2)
                             .SetString("var3", var3)
                             .ExecuteUpdate();

Where Class is the class that belongs to the NHibernate mapping.

So, to summarize:

  1. ExecuteUpdate on a SIMPLE session.CreateQuery gives me back the number of affected rows (GOOD)
  2. ExecuteUpdate on a COMPLEX session.GetNamedQuery gives me back -1 (BAD)
  3. This same complex stored procedure gives me back the desired 8700 when I execute it in SSMS (GOOD)

Anyone has an idea of how to fix 2?

Tjab
  • 368
  • 1
  • 4
  • 18
  • 1
    Your question is very similar to these questions but they return `-1` for all cases in **entity framework** have a look at them here:http://stackoverflow.com/questions/32140774/getting-data-from-stored-procedure-with-entity-framework/ And here: http://stackoverflow.com/questions/31709284/stored-procedure-return-1-for-all-cases-in-entity-framwork – Salah Akbari Apr 05 '16 at 12:48
  • Thank you, reading in to it now. – Tjab Apr 05 '16 at 13:24
  • @S.Akbari I'm kind of confused by the first variable they create (db), and how they call the stored procedure. It's completely different from how I call it within NHibernate. Also I don't see how to "Import the stored procedure as a Function. Right-click on the workspace area of your Entity model and choose Add -> Function Import." (This must be one of the most idiotic questions, but what is the workspace area of my Entity model? :S). – Tjab Apr 05 '16 at 13:31
  • 1
    What about changing your stored procedure as suggested in the second link? – Salah Akbari Apr 05 '16 at 13:38
  • Using words from the two links you gave, I googled some more and found this: http://csharptechies.blogspot.co.uk/2013/04/how-to-get-return-value-from-stored.html which actually seems to work. I am going to look into this solution combined with the `GetNamedQuery` (mapped) `.ExecuteUpdate()` combination instead of the `CreateSQLQuery` and `.UniqueResult` combination. – Tjab Apr 05 '16 at 13:51

1 Answers1

2

Using http://csharptechies.blogspot.co.uk/2013/04/how-to-get-return-value-from-stored.html I got my code working. In the procedure, replaced RETURN @@ROWCOUNT with SELECT @@ROWCOUNT

In the C# code, I replaced .ExecuteUpdate() with .UniqueResult(). UniqueResult returns an object, which will contain the @@ROWCOUNT value (need to convert to int as stated in the link above).

So the solution is a combination (I'd like to use the mapping):

  1. Use SELECT instead of RETURN
  2. Use .UniqueResult() instead of .ExecuteUpdate()

Edit: I got another problem, the query had a timeout whenever there was a large number of records to be removed. I fixed this with the help of other questions, such as SQL Server: Effects of using 'WITH RECOMPILE' in proc definition?.

  1. Use WITH RECOMPILE in a complex query on large tables (my query involved a left outer join, min(id) and group by's, the number of records to be affected are often around 20.000 but can run up to 100.000+ and my table has over 350.000.000 records in it) to avoid timeouts.
Community
  • 1
  • 1
Tjab
  • 368
  • 1
  • 4
  • 18
  • I have done so :) I get an error at this moment which I didn't get yesterday, so it might not be working still :( I'll get back to it asap. – Tjab Apr 06 '16 at 11:34
  • I feel like the query worked because I used data that did not exist. If I use Var1, Var2 and Var3 and set them to `value_does_not_exist` the query is executed. As soon as it finds data, it gives me an error saying `could not execute query ... [SQL: exec StoredProcedureName @p0, @p1, @p2]` **edit**: it does not give this error when I use values that are NOT in the database. Very strange? Does it have something to do with the return value/delete rights or something? :S – Tjab Apr 06 '16 at 11:51
  • Not sure what exactly happened but as you guessed I think it might be the the return value issue. I don't know about *NHibernate* but EF cannot support stored procedure return scalar values out of the box. – Salah Akbari Apr 06 '16 at 12:01
  • @S.Akbari I found out what the problem is, not sure how to solve yet: it worked when there are 3 duplicated values (it removes 2 of them in no time at all). However, when there are 78297 records to be removed, the query times out. The conclusion: my query is bad and I should feel bad. **BUT** when I run the stored procedure from SSMS, it takes 4 seconds to delete the 78297 records. So the question is, why does the query take more than 30 seconds (and time-outs) when I run it from Visual Studio (my web service). – Tjab Apr 06 '16 at 12:12
  • I suggest you do this in EF also and compare the results. – Salah Akbari Apr 06 '16 at 12:18
  • Let me know what the problem was when you resolve it, I'm curious. – Salah Akbari Apr 06 '16 at 12:43
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108409/discussion-between-tjab-and-s-akbari). – Tjab Apr 06 '16 at 13:31