locked
How do I get the client context to work properly with relationships? RRS feed

  • Question

  • Hi,

    I am getting an error when I try to update the relationships between User and Workgroup. As  you can see in the code below, I DeleteLink, DetachLink,  user.tblWorkgroups.Clear()  and context.UpdateObject(user) before I AddLink again but to no avail.

    Please could  you shed some light?

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
      foreach (var wg in user.tblWorkgroups)
                {
                    if (wg!=null)
                    {
                      
                        context.DeleteLink(user, "tblWorkgroups", wg);
                        context.DetachLink(user, "tblWorkgroups", wg);
                    }
                }
               
                if(user.tblWorkgroups!=null)
                {
                    user.tblWorkgroups.Clear();
                    context.UpdateObject(user);
                }

                foreach (var wg in lstBoxWorkGroup.SelectedItems)
                {
                    context.AddLink(user, "tblWorkgroups", wg as tblWorkgroup);
                }

               context.BeginSaveChanges(SaveChangesOptions.ContinueOnError, new AsyncCallback(PersistChanges), null);

    }

    This is the error: <message>Violation of PRIMARY KEY constraint 'PK_tblUserInWorkgroup'. Cannot insert duplicate key in object 'dbo.tblUserInWorkgroup'.&#xD;
    The statement has been terminated.</message>

    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code></code>
      <message xml:lang="en-GB">An error occurred while processing this request.</message>
      <innererror>
        <message>An error occurred while updating the entries. See the inner exception for details.</message>
        <type>System.Data.UpdateException</type>
        <stacktrace>   at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)&#xD;
       at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)&#xD;
       at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)&#xD;
       at System.Data.Services.Providers.ObjectContextServiceProvider.SaveChanges()&#xD;
       at System.Data.Services.DataService`1.HandleNonBatchRequest(RequestDescription description)&#xD;
       at System.Data.Services.DataService`1.HandleRequest()</stacktrace>
        <internalexception>
          <message>Violation of PRIMARY KEY constraint 'PK_tblUserInWorkgroup'. Cannot insert duplicate key in object 'dbo.tblUserInWorkgroup'.&#xD;
    The statement has been terminated.</message>
          <type>System.Data.SqlClient.SqlException</type>
          <stacktrace>   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)&#xD;
       at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)&#xD;
       at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()&#xD;
       at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)&#xD;
       at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)&#xD;
       at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)&#xD;
       at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)&#xD;
       at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)&#xD;
       at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()&#xD;
       at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary`2 identifierValues, List`1 generatedValues)&#xD;
       at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)</stacktrace>
        </internalexception>
      </innererror>
    </error>

    Cheers

    C

     

     

    Thursday, October 6, 2011 2:55 PM

All replies

  • Why are you detaching the link after call delete? Remove the call to DetachLink and hopefully that should make it work. Also, you do not need to Update the object unless you are making change to some of its non-relationship properties. If in the code above, you just want to remove all the links and add a bunch of new links, i would do the following:

     

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
        foreach (var wg in user.tblWorkgroups)
        {
            if (wg!=null)
            {
                context.DeleteLink(user, "tblWorkgroups", wg);
            }
        }
    
        if(user.tblWorkgroups!=null)
        {
            user.tblWorkgroups.Clear();
        }
    
        foreach (var wg in lstBoxWorkGroup.SelectedItems)
        {
            context.AddLink(user, "tblWorkgroups", wg as tblWorkgroup);
        }
    
        context.BeginSaveChanges(SaveChangesOptions.ContinueOnError, new AsyncCallback(PersistChanges), null);
    }
    

    Thanks

    Pratik


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, October 6, 2011 4:56 PM
    Moderator
  • Hi Pratik,

    Many thanks for the reply and help.

    I tried your code above and I got the folloing error when I use this code context.AddLink:

    "The context is already tracking the relationship."

    This is the line that throws the error:

    foreach (var wg in lstBoxWorkGroup.SelectedItems)
    {
        context.AddLink(user, "tblWorkgroups", wg as tblWorkgroup);
    }

    Do you have any ideas of how to get it to work?

    Cheers

    C

     

     

     

     

     

     

     

    Thursday, October 6, 2011 6:24 PM
  • It means that you are trying to delete and add the same relationship back again. By same relationship, i meant you are adding the same clr instance of workgroup that you removed.

    Can you try calling the SaveChanges after all the deletes and then call SaveChanges again after all the inserts?

    Thanks

    Pratik

     

     


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, October 6, 2011 11:06 PM
    Moderator
  • Hi Pratik,

    Thanks again for your help.

    I have tried calling the SaveChanges after deleting all related workgroup entities and also after the inserts but I still get the same error:

    "The context is already tracking the relationship."

    Do you think there could be a bug in the Context class generated by the WCF Data Service?

    Please see the code below:

    private void btnSave_Click(object sender, RoutedEventArgs e)
    {
        foreach (var wg in user.tblWorkgroups)
       {
            if (wg!=null)
            {
                context.DeleteLink(user, "tblWorkgroups", wg);
            }
        }

        if(user.tblWorkgroups!=null)
        {
            user.tblWorkgroups.Clear();
        }

        context.BeginSaveChanges(SaveChangesOptions.Batchr, OnDeletedSaved, null);


        foreach (var wg in lstBoxWorkGroup.SelectedItems)
        {
            //Error happens here
              context.AddLink(user, "tblWorkgroups", wg as tblWorkgroup);
        }

        context.BeginSaveChanges(SaveChangesOptions.ContinueOnError, new AsyncCallback(PersistChanges), null);
    }
              

    Cheers

    C

     

    Friday, October 7, 2011 1:32 PM
  • Hi,

    After two years, i managed it to work.

                    _dc.AttachTo("PrestatairesFormations", prestataire, "*");
                    _dc.LoadProperty(prestataire, "DomainesDeCompetence");

                    foreach (DomainesDeCompetenceItem dom in prestataire.DomainesDeCompetence)
                    {
                        _dc.DeleteLink(prestataire, "DomainesDeCompetence", dom);
                    }
                    prestataire.DomainesDeCompetence.Clear();

                    _dc.UpdateObject(prestataire);
                    _dc.SaveChanges(SaveChangesOptions.Batch);

                    if (jsonDomComp != String.Empty)
                    {
                        foreach (string domComp in jsonDomComp.Split(';'))
                        {
                            DomainesDeCompetenceItem toAdd =
                                _dc.DomainesDeCompetence.Where(d => d.Id == Int32.Parse(domComp)).FirstOrDefault();

                            if (toAdd == null) continue;

                            prestataire.DomainesDeCompetence.Add(toAdd);

                            _dc.AddLink(prestataire, "DomainesDeCompetence", toAdd);
                        }
                    }
                    if (WebSecurity.CurrentUserName != prestataire.NomPrestataire)
                    {
                        UpdateUserName(prestataire);
                    }
                    _dc.UpdateObject(prestataire);
                    _dc.SaveChanges(SaveChangesOptions.Batch);

    Bye bye

    Friday, August 9, 2013 8:26 AM