I'm having such a problem: got dataset with a table(s). Say, we have already several records in a table which has a primary key (autoincrement). Basically, program works fine until I insert a new row. Even I use method AcceptChanges or Update, the new row is commited but it existing datatable object lacks the newest primary key value which I need for furhter processing. Is the only method to reload all the table from database again or there is a better way for it?
Thanks,
Ray
You should add ';select SCOPE_IDENTITY()' to the end of your insert sql statement attached to your data adapter. That will read back the last inserted value generated by autoincrement and update your dataset.
I.e, your insert sql should resemble this:
insert into sometable(column1,column2) values(#column1,#column2); select * from sometable where primarykeycolumn=scope_identity()
Your existing dataset will then contain the primary keys when dataadaper.Update(dataset) returns.
If you have a connection object you could use
int = (int)conn.executeScalar("SELECT ##IDENTITY")
Modified by what datatype your primary key is.
This has to be done directly before any other operations as a new insert will replace the stored value in ##IDENTIY
Related
I've written a program in VB (although I'm equally comfortable with C#, so please answer in either language) that is used to insert a large amount of data into a table in my SQL server DB.
The way I've planned on doing it is:
To get the table's Schema from the DB using the SqlDataAdapter.FillSchema method.
Add the many rows of data to my DataTable
Use SqlBulkCopy (.WriteToServer(dtToCopy.CreateDataReader)) to load in the data
I've done this many times before and it's proven very efficient. My problem is that the table I'm writing to has an auto-incrementing primary key column, RowNum.
Now I know I could re-query my table after getting the schema and get the latest value of RowNum and simply write in the values myself into the corresponding column in my DataTable, but my fear is that the table may change between the time of my query and the time of my write, in which case, I could have un-desirable results.
I've seen posts relating to MissingSchemaAction > AddWithKey, but I'm not sure exactly how I could implement it in my case?
Would I just remove the primary key and delete the RowNum column from my DataTable?
And, if so, at what point do I set that property? It doesn't seem to be a property of the DataTable and I don't see where to add it in the SqlBulkCopy.
Thanks!!!
After a lot of searching, I found the solution myself.
Basically, I had to:
Set the PrimaryKey property of my DataTable to Nothing
Remove the RowNum column from my DataTable
Use ColumnMappings for my SqlBulkCopy so every other column is mapped and the identity is left out
Then, since it is a primary key and set as auto-increment in the DB, it gets automatically assigned the correct values at the time of load.
Hope this helps others!!!
Main Source:
SqlBulkCopy Insert with Identity Column
Probably sounds like a silly question, but there is an aspect about it I would like to know:
I'm working with objects that have a Guid-property for PrimaryKeys, which gets auto-generated in the database. I am using Entity Framework, Code First. If I do a Console.WriteLine with this property before saving, the value is
00000000-0000-0000-0000-000000000000.
After using Add and SaveChanges in the context, if I do a Console.WriteLine again with the same property, I have a value:
615f98eb-4ced-422a-877f-b9caa6f2b91f
Obviously, the object in memory has been updates. But I want to know how. The Guid is genereated in the database, so what happens?
Does the Guid-property of the object simply get updated from the database through EF, or does EF reload the entire object into memory after saving it in the database?
I would like to know, because that will determine how I design NUnit-tests in the same project.
Your EF object is updated when you call domainContext.SaveChanges(); Your new Id is generated by SQL database and value of Id is return value from DB. It is same for data types int, Guid and similar.
EF does not only submit an Insert/Update statement, at the same time it does a get statement to retrieve the generated primary key. In fact it is one single query. Your entity's primary key is then updated with the retrieved one. No magic behind this.
That's also one of the reason why batch updates / inserts are not supported. Every entity has to be updated / inserted on its own.
This is a query that is being executed when inserting an entity with a computed int primary key:
insert [dbo].[TestTable]
([Name])
values ('myname' /* #0 */)
select [ID]
from [dbo].[TestTable]
where ##ROWCOUNT > 0
and [ID] = scope_identity()
As you can see, the insert statement is followed by a select statement retrieving the computed columns (in this case ID). If there are more computed columns they're all selected here.
I use asp.net 4 and DataSets for accessing the database. There are two tables with one-to-one relationship in the database. It means that both tables have the same column as a primary key (say Id), and one of tables has #identity on this column set.
So in general if we want to insert, we insert first into the first table, than insert into the second table with id.table2 = id of the corresponding record in table1.
I can imagine how to achieve this using stored procedure (we would insert into the first table and have id as an out parameter and then insert into the second table using this id, btw all inside one transaction).
But is there a way to do it without using a stored procedure? May be DataSets \ DataAdapters have such functionality built in?
Would appreciate any help.
Today it is so quiet here... Ok if anybody is also looking for such a solution, I've found a way to do it.
So our main problem is to get the id of the newly created record in the first table. If we're able to do that, after that we simply supply it to the next method which creates a corresponding record in the second table.
I used a DataSet Designer in order to enjoy the code autogeneration feature of the VS. Let's call the first table TripSets. In DataSet Designer right click on the TripSetsTableAdapter, then Properties. Expand InsertCommand properties group. Here we need to do two things.
First we add a new parameter into the collection of parameters using the Parameters Collection Editor. Set ParameterName = #TripId, DbType = Int32 (or whatever you need), Direction = Output.
Second we modify the CommandText (using Query Builder for convenience). Add to the end of the command another one after a semicolon like that:
(...);
SELECT #TripId = SCOPE_IDENTITY()
So you will get something like this statement:
INSERT INTO TripSets
(Date, UserId)
VALUES
(#Date,#UserId);
SELECT #TripId = SCOPE_IDENTITY()
Perhaps you will get a parser error warning, but you can just ignore it. Having this configured now we are able to use in our Business logic code as follows:
int tripId;
int result = tripSetsTableAdapter.Insert(tripDate, userId, out tripId);
// Here comes the insert method into the second table
tripSetTripSearchTableAdapter.Insert(tripId, amountPersons);
Probably you will want to synchronize this operations somehow (e.g. using TransactionScope) but it is completely up to you.
I am working on windows application using c# and MySQL.
I inserted new record by reading text file into MySQL database, Database having no primary key but combination of four columns we can consider as component of primary key (but actually database having no primary key).
I know how to add and update record using DataAdapter and DataSet. But I can not update a record in the database having no primary key.
Can you please guide me, how can I update a record in the database with a database having no primary key.
Thanks.
Assuming you have next table:
column1,
column2,
..
columnN,
target -- column to update
then use:
UPDATE table
SET
target = #target
WHERE
column1 = #va1, column2 = #val, -- etc specify all columns in table
If you have duplicated (absolute equal) records, you will update all of them.
For this to work with a Dataset you need to define your update command "By-Hand".
You need to set the proper DataAdapter.UpdateCommand.
In my point of view it would be a better approach to just add a primary key column to the table.
I am using C#.Net application in which i created a dataset.Now i want to create a method in which i will enter a record in one table which will return a value ie primary key.Now by using that primary key i have to insert records in 5 tables and i have to use that primary key as a foreign key for this 5 tables using dataset.
You need to tell your parent table's table-adapter to refresh the
data-table after update operation.
This is how you can do that.
Open the properties of ParentTableAdapter -> Default Select Query -> Advnaced options. and Check the option of Refresh the data table. Save the adapter now. Now when you call update on table-adapter, the data-table will be updated [refreshed] after the update operation and will reflect the latest values from database table. if the primary-key or any coloumn is set to auto-increment, the data-table will have those latest value post recent update.
Now you can Call the update as ParentTableAdapterObj.Update(ds.dataTable);
Read latest values from the ParentDataTable(ds.dataTable) coloumns and assign respective values into the child table before update. This will work exactly the way you want.
alt text http://ruchitsurati.net/files/tds1.png
Have you tried temporary key linkage until the DB generates the final key? Works great for me.