ForeignKeyConstraint exception

Jun 10, 2011 at 12:05 PM

I am having a ForeignKeyConstraint exception when assigning the int id of the FK. I think it might be related to this other thread: http://nhydrate.codeplex.com/discussions/258816

I am using the nHydrate DAL.

I have 2 tables (and equal classes): livretes and mudancas_estado_livrete.

Table livretes has a FK field, livretes.ultima_mudanca_estado_id, which references the internal id of mudancas_estado_livrete by a FK constraint.

I have a member method in livretes.cs where i am executing this code:

 

		public void UpdateToNewEstadoLivreteAndPersist (TipoEstadoLivrete novoEstadoLivrete, int userID, string observacoes)
		{
			this.Persist ();

			mudancas_estado_livreteCollection melc = new mudancas_estado_livreteCollection ();
			mudancas_estado_livrete mudancaEstadoLivrete = melc.NewItem ();
			melc.AddItem (mudancaEstadoLivrete);

			mudancaEstadoLivrete.estado_livrete_id = (int)novoEstadoLivrete; //Filling object
			mudancaEstadoLivrete.livreteid = this.livreteid; //Filling object
			mudancaEstadoLivrete.utilizador_responsavel_id = userID; //Filling object
			if (!string.IsNullOrEmpty (observacoes))
			{
				mudancaEstadoLivrete.observacoes = observacoes; //Filling object
			}
			mudancaEstadoLivrete.Persist ();

			//Here, a select to the database shows that this FK ID already exists and everything is ok
			this.ultima_mudanca_estado_id = mudancaEstadoLivrete.mudanca_estado_livrete_id; //ForeignKeyConstraint mudancas_estado_livreteLivretes_estados_livretelivretesRelation requires the child key values (47) to exist in the parent table.
			this.Persist ();
		}

I think that this should not fail. In one place of the application it always works correctly. In another place of the application it always fails.

I can't see anything diferent i am doing in both places of the application (although something probably is diferent).

I am not doing anything weird with the DAL, i am just using it's methods in a plain way (this member method of the class livretes is almost an unique exception, the DAL is almost as original and i am not messing with the internal collections/domains/stuff).

I can't seem to replicate the problem in a new project made specifically to test the error.

 

I don't know what to do.....

 

Jun 10, 2011 at 12:45 PM

nHydrate DAL must be having some sort of desync for sure.

I changed the code to this and it no longer generates an FKConstraint exception (notice the last 3 lines of code):

		public void UpdateToNewEstadoLivreteAndPersist (TipoEstadoLivrete novoEstadoLivrete, int userID, string observacoes)
		{
			this.Persist ();

			mudancas_estado_livreteCollection melc = new mudancas_estado_livreteCollection ();
			mudancas_estado_livrete mudancaEstadoLivrete = melc.NewItem ();
			melc.AddItem (mudancaEstadoLivrete);

			mudancaEstadoLivrete.estado_livrete_id = (int)novoEstadoLivrete; //Filling object
			mudancaEstadoLivrete.livreteid = this.livreteid; //Filling object
			mudancaEstadoLivrete.utilizador_responsavel_id = userID; //Filling object
			if (!string.IsNullOrEmpty (observacoes))
			{
				mudancaEstadoLivrete.observacoes = observacoes; //Filling object
			}
			mudancaEstadoLivrete.Persist ();

			//No longer use "this", but use a newly selected object, probably fresh from BD
			livretes livrete = livretes.SelectUsingPK (this.livreteid);
			livrete.ultima_mudanca_estado_id = mudancaEstadoLivrete.mudanca_estado_livrete_id;
			livrete.Persist ();
		}

Jun 10, 2011 at 1:43 PM

Only now i have a new problem.

The original instance of that class (livretes) is no longer syncronized with the database (actually, it seems that it wasn't synched before, anyway).

How do i force that instance to syncronize with the data source?

It doesn't appear to have a method like

nHydrateDalObject.ReSyncWithDataSource()

Which is usefull for situations where we have an object loaded by the DAL and we expect the data source (like the database) to have been changed from an external source (other application, or like in this situation).

Jun 10, 2011 at 5:31 PM
Edited Jun 10, 2011 at 5:39 PM

I do this before I add the new item to the collection now to ensure that all the foreign-keys will be met in my subdomain.

I have begun to do this when my subdomain for an object goes more than a single relationship deep. 

I no longer get any FK exceptions and I only need one Persist on the subdomain (which is what I was after)

I have no synchronization issues.

 

Private Sub VerifyPersonFks(ByVal PersonID As Integer)
        Dim Person As Persons = PersonsCollection.SelectUsingPK(PersonID)
        If (From g In _data.ParentCollection.SubDomain.GetCollection(Of GendersCollection)() Where Person.GenderID = g.GenderID).Count <= 0 Then
            _data.ParentCollection.SubDomain.Merge(CType(GendersCollection.SelectUsingPK(Person.GenderID), Genders).ParentCollection.SubDomain, True, MissingSchemaAction.AddWithKey)
        End If
        If (From m In _data.ParentCollection.SubDomain.GetCollection(Of MaritalStatusesCollection)() Where Person.MaritalStatusID = m.MaritalStatusID).Count <= 0 Then
            _data.ParentCollection.SubDomain.Merge(CType(MaritalStatusesCollection.SelectUsingPK(Person.MaritalStatusID), MaritalStatuses).ParentCollection.SubDomain, True, MissingSchemaAction.AddWithKey)
        End If
        If (From p In _data.ParentCollection.SubDomain.GetCollection(Of ProvincesCollection)() Where Person.ProvinceID = p.ProvinceID).Count <= 0 Then
            _data.ParentCollection.SubDomain.Merge(CType(ProvincesCollection.SelectUsingPK(Person.ProvinceID), Provinces).ParentCollection.SubDomain, True, MissingSchemaAction.AddWithKey)
        End If
        If (From t In _data.ParentCollection.SubDomain.GetCollection(Of PersonsCollection)() Where t.PersonID = Person.PersonID).Count <= 0 Then
            _data.ParentCollection.SubDomain.Merge(Person.ParentCollection.SubDomain, True, MissingSchemaAction.AddWithKey)
        End If
    End Sub