views:

160

answers:

5

I'm a bit of a noob with DAO and SQL Server and I'm running into a problem when I'm trying to insert values into two tables that have a relation. The table Photos has a gpsId field which has a foreign key relation with the id field of the GPSLocations table. I want to create a new Photos entry linked to a new GPSLocation, so the code looks something like this:

gpsRow = dataset.GPSLocations.AddGPSLocationsRow("0.0N", "3.2W");
dataset.Photos.AddPhotosRow(@"c:\path\file.jpg", gpsRow);
tableAdapterManager.UpdateAll(dataset); 

However this results in the following error:

A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = photoToGps ]

I'm using SQL Server CE. Is my understanding correct that the TableAdapterManager should be handling this hierarchical update? I just dragged these tables onto the XSD view and relied on its automatic creation of the wrapper classes. Do I need to change anything about the relation (eg to make it a Foreign Key constraint)? I've noticed that under some circumstances the gps id is positive and sometimes negative, is that relevant?

EDIT: I've also ensured that the update property is set to CASCADE, which results in the same error. Hierarchical updates are set to true and there is a foreign key constraint between the two tables in the designer.

A: 

Since the column photoToGps (foreign key) depends on the primary key (id), you cannot add a photoToGps unless there is a corresponding id present. So what you need to is individual updates, instead of doing an UpdateAll. First update the GPSLocations table, and then the other table. That way, you will have an id existing before you add a photoToGPS for it.

Mamta Dalal
Thanks, but I had tried that before trying the TableAdapterManager, which I thought is supposed to deal with this kind of update where there is a relation which implies one table has to be updated first.
the_mandrill
+1  A: 

Did you enable Hierarchical Updates as described here?

Joe Stefanelli
Thanks, I'll give that a try
the_mandrill
Yes, it was already set true -- that's the default in VS2008
the_mandrill
+1  A: 

Is there a foreign key constraint between the two tables (there should be a line on the XSD designer connecting them)? Since your fields are named differently it might not have been automatically added when you dragged the tables to the design surface.

ktharsis
Yes, there is a foreign key constraint. I've tried the different options in the XSD designer to enable constraints or relations. I get the same result.
the_mandrill
+1  A: 

It's just the configuration of your data set. Doubleclick the relation beween the tables in the Visual Studio's dataset designer, choose Both Relation And Foreigh Key Constraint option and in the Update Rule field choose Cascade option and that must be it.

Some information about the subject is in MSDN, you can look here http://msdn.microsoft.com/en-us/library/bb629317.aspx and go to the related topics.

Dmitry Tashkinov
As mentioned in my response to ktharsis and in my edit, I've enabled the foreign key constraint and the update rule is set to cascade.
the_mandrill
You said there you had tried the different options, but I didn't know you had tried exactly this. Just "Foreigh Key Constraint" won't work. There must be exactly "Both Relation And Foreigh Key Constraint" together whith Update Rule "Cascade". I've just tried it and it worked. Maybe that's because you're using SQL Server CE and I'm using MS SQL 2008 Developer Edition.
Dmitry Tashkinov
I've now found that this is a difference between SQL Server CE and the full SQL Server -- see my own answer below
the_mandrill
+1  A: 

I've managed to track down the source of this problem, which boils down to a limitation of SQL Server CE compared with the full SQL Server. It turns out the major hint that something wasn't right was because the ids were negative. The ids are negative in the DataSet before the row is inserted into the database, at which point it gets resolved to a positive index. The fact that it wasn't becoming a positive index happened because the TableAdapterManager normally does a batch statement of INSERT followed by a SELECT to update the id. However, SQL Server CE doesn't support batch statements, so this requires extra code to be written so that we simulate the SELECT step by responding to the RowUpdated event. This MSDN article explains the steps.

the_mandrill
Interesting. I wonder if the same issue exists in LINQ To SQL and Entity Framework, which are Microsoft's own alternatives to DataSets.
Dmitry Tashkinov