How to get the Scope_identity value for the parent record using VS19 with bound datasets - vb.net

I have two tables in MSSQL which are related tbl1.PK tbl2.PK, tbl2FK(_tbl1PK)
I have created a dataset in Visual Studio and they show up with the relation
when I drop the tables as datagrids onto a form I get the parentDG and childDG.
VS adds in the binding navigator which adds the save procedure
tbl1.bindingsource.endedit
tableadaptermanager.updateall
When I add data to the parentDG and press save the data gets saved to the DB.
When I add a new parent and then add a new child details and press save I get
System.Data.SqlClient.SqlException: 'The INSERT statement conflicted with the FOREIGN KEY constraint "FK_tblChild_tblParent". The conflict occurred in database "xxxxx", table "dbo.tblParent", column 'PK'.
I have tried updating the parentTableadapter and then ds.acceptchanges but I can not get the new child row to update.
I understand why but my questions are:
isn't the VS IDE supposed to handle this?
if isn't for me so I presume I need to get the new tbl1PK (scope_identity).
I can see in the dataset code the insert command:
Me._adapter.InsertCommand.CommandText = "INSERT INTO [] FROM tbl1 WHERE (PK= SCOPE_IDENTITY())"
BUT I cannot for the life of me see how to get this value.
I have a lot of tables with a lot of columns which is why I want/need to use the power of the IDE to populate and bind my controls and so I really do not want to go down the route of manually creating my datasets.
I have searched and searched on this and can't find anything that speaks to how you do this using VS auto generated code.
thanks
John

I just tested and the addition of the query in the InsertCommand happened automatically so you must not have done something properly. Here's EXACTLY what I did:
Created a new database named Test on my local default SQL Server instance via SSMS.
Added a table named Parent with columns ParentId (int, PK, identity) and ParentName (varchar).
Added a table named Child with columns ChildId (int, PK, identity), ParentId (int) and ChildName (varchar).
Created a foreign key in the Child table to the ParentId column from the ParentId column in the Parent table, setting the Update Rule to Cascade.
Created a new VB Windows Forms application project.
Added a new Data Source via the Data Sources window for the Test database.
Opened the TestDataSet from the Solution Explorer in the DataSet designer.
Selected the DataRelation between the two DataTables.
In the Properties window, clicked Edit Relation.
Checked 'Both Relation and Foreign Key Constraint', when Update Rule changed automatically to Cascade.
At this point, but even after step 7, I was able to select the ParentTableAdapter in the designer, expand the InsertCommand and view the CommandText to see this:
INSERT INTO [dbo].[Parent] ([ParentName]) VALUES (#ParentName);
SELECT ParentId, ParentName FROM Parent WHERE (ParentId = SCOPE_IDENTITY())
If you don't see that, you can set it yourself. What happens now is that, when the InsertCommand is executed to insert a new record, that query immediately retrieves the data from that record back into the DataRow in your DataSet. That will update the ParentId column with the newly generated value and the Update Rule will cause that new value to cascade to any related DataRows in the Child DataTable, so you can just go ahead and insert them without worry.

Related

MS Access Append Query, no error message, no result, no known cause

Here goes with as much detail and clarity as I can give you...
Goal: Append portions of "Validated" table to several existing tables, all related by "PropertyID" field
Problem: Even a very basic append query fails to work. I created a query in design view to append [PropertyName] from the Validated table to the GeneralProperty table. Both are text field, same length, not required, allowed zero length, not indexed. When I run the query nothing happens. No error message, no result. The GeneralProperty table remains empty. I went to SQL view and pressed run on the following query and still got nothing:
INSERT INTO GeneralProperty ( PropertyName )
SELECT [Import2-Validated].PropertyName
FROM [Import2-Validated];
Additional Info:
Primary Key is "PropertyID" and it is an autonumbered field.
GeneralProperty table contains the above Primary key
Four other tables contain "PropertyID", joined by a relationship
Relationship enforces referential integrity, and cascades updates+deletes
Append query does work to append text from the "Validated" table to tables other than GeneralProperty, so long as I do not try to append PropertyID in the query.
Database is working as expected for manual entry through a form. All relationships and autonumbering of the primary key work as expected.
Using MS Access 2010
Edits
Result of SELECT [Import2-Validated].PropertyName is a popup to enter parameter value
Haven't specified DoCmd.SetWarnings=False in code anywhere

Can't create BigQuery View after adding a new column into a table

I add a new column called "key" by doing an update on my existing table.
I insert some dummy data with "key" value and run the following query:
SELECT key, name, id ...
FROM table
GROUP BY key, name, id ...
The query run correctly with following results:
existing data has key = null and existing data intact
dummy data contains valid key but no real data
However when I try to save this query as a View I get the following error:
Failed to create view. Field 'key' not found in table 'foo.table'.
This doesn't make sense because the column exists in the table. Does anyone come across this? My current work around is to just run the query without saving it as a View. However when I have more complicated queries involving this new "key" column it would be handy to be able to create Views containing the new column.
This issue has been acknowledge by Google and fixed via Enterprise Support ticket #04171323
Creating views should work now when a table has been altered with a new column.

How to link foreign key to auto-incremented primary key in Oracle?

I have two tables whose common field is Load_ID. The PK of the first has a one-to-many relationship with the FK of the second. For example:
Table1:
1, someValue
Table2:
1, value1, ...
1, value2, ...
1, value3, ...
I've embedded the actual insert statement in an ASP.NET class where the values are taken from user input:
"INSERT INTO Compare_Header_Table VALUES
(compare_sequence.nextval, //other values are inserted here)
The sequence I'm using to auto-increment the PK is CREATE SEQUENCE compare_sequence;
This seems to work even without creating a trigger or specifying any parameters because the sequence defaults to an increment of 1 and an initial value of 1, which is fine for my purposes.
Where I'm running into problems is trying to link the FK from the second table to the PK of the first. I cannot simply use compare_sequence.currval because I have a separate method for inserting into each table, so I'm creating a new connection each time. I don't want to combine these into one method because that will involve changing the logical structure of my C# class, which I'd rather leave intact.
Any suggestions for how to make this work?
What you can do is use the RETURNING cause to get the assigned value:
INSERT INTO Compare_Header_Table (ID) VALUES
(compare_sequence.nextval)
returning id into some_value;
This some_value is a local variable which you need to pass out of your first class and hand on to the second class. How precisely you do that rather depends on your architecture.
Incidentally I do hope that when you say 'I'm creating a new connection each time' this is some c# jargon and you're not really creating a new database conection each time. Because that's a pretty expensive operation.
The other thing is, if you're in different sessions for creating the parent and child records what happens to the transaction? You'll have to commit each insert (otherwise the new parent record won't be visible to the foreign key validation when you try to insert the child).
If you want the INSERT operations to be done in separate sessions, you'll need to retrieve the generated key from the first statement and pass that in to the method that inserts the data into table2. One way to retrieve the generated key without requiring a database round-trip would be to do something like
INSERT INTO compare_header_table
VALUES( compare_sequence.nextval,
... )
RETURNING name_of_primary_key_column
INTO :bind_variable

Update command against parent DataTable accepting changes on child Datatable?

I have a parent-child relation setup between two tables. The parent table is setup with an auto increment value for its primary key. This is working fine and the new row in the parent DataTable is refreshed with the actual value of the key that was just inserted when I call Update on the TableAdaptor.
The problem is that the rows from the child table are not being inserted into the DB. For debug purposes, I added changesBefore and changesAfter to the code sample to see what changed rows exist in the child table. When I step through the code with a debugger, changesBefore constains the new child rows. changesAfter is Nothing. Its almost as if calling Update against the header table is triggering AcceptChanges on the child table.
I am familiar with insert/updating with DataTables and TableAdapters but this is my first attempt at using an autoincrement on a parent table. What am I missing here?
Dim changesBefore = _ds.ResponseDetails.GetChanges
headersTa.Update(_ds.ResponseHeaders)
Dim changesAfter = _ds.ResponseDetails.GetChanges
detailsTa.Update(_ds.ResponseDetails)
After doing the header update, you need to update the linking field in the detail record with the auto generated id from the header record. This does not happen automatically for you.
This is working now. Turns out there is an AcceptRejectRule property for each relation in a data set. I had the rule set to Cascade so it was basically cascading AcceptChanges down to the child table when Update was called against the parent. Changing the rule to None resolved my issue.
http://msdn.microsoft.com/en-us/library/system.data.acceptrejectrule(v=vs.80).aspx

Inheritance in database?

Is there any way to use inheritance in database (Specifically in SQL Server 2005)?
Suppose I have few field like CreatedOn, CreatedBy which I want to add on all of my entities. I looking for an alternative way instead of adding these fields to every table.
There is no such thing as inheritance between tables in SQL Server 2005, and as noted by the others, you can get as far as getting help adding the necessary columns to the tables when you create them, but it won't be inheritance as you know it.
Think of it more like a template for your source code files.
As GateKiller mentions, you can create a table containing the shared data and reference it with a foreign key, but you'll either have to have audit hooks, triggers, or do the update manually.
Bottom line: Manual work.
PostgreSQL has this feature. Just add this to the end of your table definition:
INHERITS FROM (tablename[, othertable...])
The child table will have all the columns of its parent, and changes to the parent table will change the child. Also, everything in the child table will come up in queries to the parent table (by default). Unfortunately indices don't cross the parent/child border, which also means you can't make sure that certain columns are unique across both the parent and child.
As far as I know, it's not a feature used very often.
You could create a template in the template pane in Management Studio. And then use that template every time you want to create a new table.
Failing that, you could store the CreatedOn and CreatedBy fields in an Audit trail table referencing the original table and id.
Failing that, do it manually.
You could use a data modeling tool such as ER/Studio or ERWin. Both tools have domain columns where you can define a column template that you can apply to any table. When the domain changes so do the associated columns. ER/Studio also has trigger templates that you can build and apply to any table. This is how we update our LastUpdatedBy and LastUpdatedDate columns without having to build and maintain hundreds of trigger scripts.
If you do create an audit table you would have one row for every row in every table that uses the audit table. That could get messy. In my opinion, you're better off putting the audit columns in every table. You also may want to put a timestamp column in all of your tables. You never know when concurrency becomes a problem. Our DB audit columns that we put in every table are: CreatedDt, LastUpdatedBy, LastUpdatedDt and Timestamp.
Hope this helps.
We have a SProc that adds audit columns to a given table, and (optionally) creates a history table and associated triggers to track changes to a value. Unfortunately, company policy means I can't share, but it really isn't difficult to achieve.
If you are using GUIDs you could create a CreateHistory table with columns GUID, CreatedOn, CreatedBy. For populating the table you would still have to create a trigger for every table or handle it in the application logic.
You do NOT want to use inheritance to do this! When table B, C and D inherits from table A, that means that querying table A will give you records from B, C and D. Now consider...
DELETE FROM a;
Instead of inheritance, use LIKE instead...
CREATE TABLE blah (
blah_id serial PRIMARY KEY
, something text NOT NULL
, LIKE template_table INCLUDING DEFALUTS
);
Ramesh - I would implement this using supertype and subtype relationships in my E-R model. There are a few different physical options you have of implementing the relationships as well.
in O-R mapping, inheritance maps to a parent table where the parent and child tables use the same identifier
for example
create table Object (
Id int NOT NULL --primary key, auto-increment
Name varchar(32)
)
create table SubObject (
Id int NOT NULL --primary key and also foreign key to Object
Description varchar(32)
)
SubObject has a foreign-key relationship to Object. when you create a SubObject row, you must first create an Object row and use the Id in both rows