views:

36

answers:

2

Hello Everybody,

I am dealing with the following problem: I use a MSSQL Stored Procedure for displaying my data in a DataGridView. The Update and Insert Commands work, but there is one problem:

On inserting a new Row, the auto-numbered primary key isn't send back to my DataAdaptar. So the insertion is successfull in the database, but the PK is left blank in the DataGridView. I allready tried some codes like:

    private void _rowUpdated(object sender, SqlRowUpdatedEventArgs e)
    {
        if (e.Status == UpdateStatus.Continue && e.StatementType == StatementType.Insert)
        {
            cmd = conn.CreateCommand();
            cmd.CommandText = "SELECT @@IDENTITY FROM " + e.Row.Table.TableName;

            DataRow r = dt.Rows[dt.Rows.Count - 1];
            r.ItemArray[0] = cmd.ExecuteScalar();
            //r.SetModified(); --> err?
            r.AcceptChanges();
        }
    }

on the DataAdapter, but nothing seems to work. All the SQL commands work fine.

When I refresh the data in the DataGridView, everyting is perfect. But the problem with this is, that the sort order and column width are adjusted. And that isn't what I want.

Can someone help me with this problem?

Looking forward for the solutions!

Thanks!

A: 

Since the connection to sql server has terminated so @@identity will become null and hence you are getting null value.

You cannot use scope_identity() here since its scope is limited to the place i.e. procedure in your case where it is called.

ident_current() always returns last identity value for the table that you specified. It might not work correct in case of replication

Update your commandText to ="Select ident_current("+e.Row.Table.TableName+")"

Here are the results of using various techniques of retrieving identity value. Replace dbo.M_PatientEntry with your table name

select ident_current('dbo.M_PatientEntry')
---------------------------------------
13

select @@identity from dbo.M_PatientEntry    
---------------------------------------
NULL
NULL

select scope_identity()    
---------------------------------------
NULL

select scope_identity() from dbo.M_PatientEntry    
---------------------------------------
NULL
NULL

Also try avoiding @@Identity rather use scope_identity() or ident_current @@identity will give you incremented value of trigger table result if you are using trigger on the same table where insertion is going on.

see this documentation

Shantanu Gupta
Hello,I tested the code like this:cmd.CommandText = "SELECT IDENT_CURRENT('" + e.Row.Table.TableName + "')";var res = cmd.ExecuteScalar();Debug.WriteLine("RESULTS:" + res);It gave the same result as with my query. But you are right, its better to use this sql function. But the problem still exists: The PK field is left empty. I guess the datarow isn't saved in the function. But all the actions I use (Update, AcceptChanges, ..) result in an infinite loop. Any suggestions?
VeeWee
@VeeWee: Why not put a breakpoint at cmd.ExecuteScalar() and check what value it gives. Try to check its result on immediate window (Alt+Ctrl+I) in VS.Net. Just copy paste this `cmd.ExecuteScalar()` and check what you are getting. Try the same query on sql server. It will give you desired result. I cant say much about working on disconnected architecture and hence cant help you much with issues related to it.
Shantanu Gupta
@VeeWee: Is this event row_updated() running under a loop ? What does this means **"all the actions I use (Update, AcceptChanges, ..) result in an infinite loop"**
Shantanu Gupta
Indeed, I should have used breakpoints. The result of the function is fine. When I take a closer look, I see that the exact row is selected, but that the first column isn't filled with the query result. Instead there is a System.DBNull value. It looks like the row is blocked? I think I cannot just change the insertCommand because I want to make 1 component for multiple tables, so the name of the PK is unknown.
VeeWee
I don't think its running in a loop. At least I didn't put it in a loop... When I try the following stuff: dt.AcceptChanges or adapt.Update(); The program starts to add rows untill I get an infinity loop error.
VeeWee
in that case you can modify your query little bit to `cmd.CommandText = "SELECT IDENT_CURRENT('" + e.Row.Table.TableName + "' as PK)";` now u can get column name as PK
Shantanu Gupta
since this query returns object type so you must check `if(result.GetType()==DBNull.Value)` DBNull hence initialize value to Null. Moreover DBNull and Null are two different entities and you cannot initialize an object with DBNull because DBNull is a different class object System.DBNull and null is a different entity
Shantanu Gupta
No, I meant the name of the PK column in the insert statement. The last ID off the database is not a problem. The problem is getting this ID into my DataTable: When I set the value of the first column in the last row to the newest Id. This value isn't saved in the DataTable.
VeeWee
@VeeWee: ok, that's an another issue. This issue u can find in topics related to working with dataset in disconnected mode
Shantanu Gupta
The strange thing is: in the row_updated function, the connection is open. So it's not in disconnected mode? I changed the adaptar: adapt.AcceptChangesDuringFill = true;adapt.AcceptChangesDuringUpdate = true;And normally after the updated Event, the function AcceptChanges is called. So when I change the datatable, the changes have to be saved, or not?I don't understand why the ID isn't placed in the first column of the last row and I don't seem to find the answer on internet. Strange :)
VeeWee
@VeeWee: I dont know whether i am right or now as i never used this way to work on database. Try to use cmd.Update() before calling AcceptChanges. SInce I feel as if this step will notify that cmd has request for update.
Shantanu Gupta
I posted the solution I found. Now the cmd isn't linked with the update command. Those 2 commands are now 2 different connections. Glad it finally works!! Thx for the help!
VeeWee
+1  A: 

Hello All,

Finally found the answer and wanted to share it:

dt.RowChanged += new DataRowChangeEventHandler(_update_fields);


    private void _update_fields(object sender, DataRowChangeEventArgs e)
    {
        try
        {
            if (e.Action == DataRowAction.Add)
            {
                conn.Open();
                cmd = conn.CreateCommand();
                cmd.CommandText = "SELECT IDENT_CURRENT('" + e.Row.Table.TableName + "')";
                dt.Rows[dt.Rows.Count - 1][0] = int.Parse(cmd.ExecuteScalar().ToString()) + 1;
                dt.AcceptChanges();
                conn.Close();
            }
            adapt.Update(dt);
        }
        catch (SqlException ex)
        {
            Debug.WriteLine(ex.Message);
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

Hope it will save you some time! :)

Gr VeeWee

VeeWee