History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: NH-727
Type: Improvement Improvement
Status: Closed Closed
Resolution: Fixed
Priority: Minor Minor
Assignee: Unassigned
Reporter: Sergey Koshcheyev
Votes: 8
Watchers: 8
Operations

If you were logged in you would be able to see more operations.
NHibernate

Allow using sql-insert with generator class="identity"

Created: 26/Sep/06 05:01 AM   Updated: 09/Oct/08 12:22 PM
Component/s: Core
Affects Version/s: 1.2.0.Beta1
Fix Version/s: 2.1.0.Alpha1

File Attachments: 1. Text File nh_727-identity-sql-insert.patch (16 kb)



 All   Comments   Change History      Sort Order: Ascending order - Click to sort in descending order
Sam Ritchie - 26/Sep/06 09:07 PM
I've managed to get this running by assuming that the custom insert sql returns a result set with the appropriate id. It might be preferable to make this behaviour configurable, eg via a 'selects-id' attribute on the <sql-insert> mapping element.

I've most likely broken something important (in particular, I haven't tested this with multiple table enitites yet), but I'm listing my code changes below in case they're useful.

in AbstractEntityPersister.PostInstantiate():

            SqlCommandInfo defaultIdentityInsert = GenerateIdentityInsertString(PropertyInsertability);
            sqlIdentityInsertString = customSQLInsert[0] == null
                                        ? defaultIdentityInsert
                                        : new SqlCommandInfo(customSQLInsert[0], defaultIdentityInsert.ParameterTypes);

in AbstractEntityPersister.Insert(object[], bool[], SqlCommandInfo, object, ISessionImplementor):

                if (customSQLInsert[0] != null)
                {
                    // Assume the custom insert sql already contains an identity select statement
                    insertSelectSQL = sql.Text;
                }
                else if (sql.CommandType == CommandType.Text)
                {
                    insertSelectSQL = Dialect.AddIdentitySelectToInsert(sql.Text, IdentifierColumnNames[0], TableName);
                }

Chris Chew - 01/Nov/07 09:24 AM
I'm attaching a patch against the trunk (rev 3075) for the changes described in this issue. The changes include:

AbstractEntityPersister.cs
    2299:2304 -- Added logic in Insert() to assume the custom sql string (if available) will return the identity id.
    2815:2820 -- Added logic in PostInstantiate() to treat the resultset of the custom sql string just like it would for a normal

NHibernate.Test.SqlTest:
    IdentityInsertWithStoredProcsTest.cs -- Abstract test case for use with many dialects
    MSSQLIdentityInsertWithStoredProcsTest.cs -- MS SQL Server dialect derivative of IdentityInsertWithStoredProcsTest
    MSSQLIdentityInsertWithStoredProcs.hbm.xml -- Mapping file for use in MSSQLIdentityInsertWithStoredProcsTest

All tests continue to pass with this fix, which seems to indicate that Sam Ritchie's concerns are not applicable.

Thanks!!!

Ivo Ramírez - 04/Jul/08 10:02 AM
Hi!
I was trying NHibernate 2.0 beta with stored procedures and I still have issues with sql-insert and identity in SQL Server (2000 and 2005).
No matter what script I specify in <sql-string>, SqlServer throws "Parameterized Query '(@p0 int,@p1 nvarchar(7),@p2 int)exec InsertTest @p0, @p1' expects parameter @p2, which was not supplied."

The query is:
exec sp_executesql N'exec InsertTest @p0, @p1',N'@p0 int,@p1 nvarchar(4),@p2 int',@p0=342,@p1=N'test',@p2=default

The entity has 2 properties and the Id. I tried to pass a dummy parameter @id to the stored procedure but I still get the same error:
exec sp_executesql N'exec InsertTest @p0, @p1, @p2',N'@p0 int,@p1 nvarchar(4),@p2 int',@p0=342,@p1=N'test',@p2=default

It seems like the problem is in the @p2=default part (I tried in the query analyzer to excute any kind of script passing default to a parameter and it breaks). When I remove this parameter or replace the value to 0 or something (but not 'default'), it works.

Thanks!!

Ignacio Vaona - 04/Aug/08 02:03 PM
In my case I am using a View in SQLServer 2000 for querying and stored procedures for inserting data.
When I try to use Id generator as "identity" instead of using the stored procedure for insert, the application is trying to update the View directly.

I had to change a little the code Sam Ritchie posted ...
In this piece ...
 if (customSQLInsert[0] != null)
                {
                    // Assume the custom insert sql already contains an identity select statement
                    insertSelectSQL = sql.Text;
                }

... I had to change this
 if (customSQLInsert[0] != null)
                {
                    // Assume the custom insert sql already contains an identity select statement
                    insertSelectSQL = customSQLInsert[0]; // I had to change this for making it work.
                }

otherwise it will be taking the default sql and will attempt to insert data into the view. And if a custom sql has been specified it should be correct to use this instead of the default sql that Nhibernate generates.

Thanks

Fabio Maulo - 09/Oct/08 12:22 PM
Thanks to James Nail to refresh the situation of this issue in nhusers maling-list.