views:

339

answers:

1

I have a very simple server model that includes a parent entity with a [Composition] list of child entities. In my client, I have 2 functions. One function removes all the child entities from the parent and the other removes all and also edits a property on the parent entity.

When I simply remove all child entities and SubmitChanges(), all is well.

When I remove all child entities and edit the parent and SubmitChanges(), there are still pending changes (HasChanges == true) when the SubmitChanges() callback is fired.

I am using Silveright 4 RTM and RIA Services 1.0 RTM.

Any ideas what is going on here?

Here are the server entities:

public class RegionDto
{
    public RegionDto()
    {
        Cities = new List<CityDto>();
    }

    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    [Include]
    [Composition]
    [Association("RegionDto_CityDto", "Id", "RegionId")]
    public List<CityDto> Cities { get; set; }
}

public class CityDto
{
    [Key]
    public int Id { get; set; }

    public int RegionId { get; set; }
    public string Name { get; set; }
}

And here is the client code:

public static class CState
{
    private static RegionDomainContext _domainContext;

    public static RegionDomainContext DomainContext
    {
        get
        {
            if (_domainContext == null)
            {
                _domainContext = new RegionDomainContext();
            }
            return _domainContext;
        }
    }

    public static void SaveChanges()
    {
        DomainContext.SubmitChanges(op =>
        {
            if (DomainContext.HasChanges && !DomainContext.IsSubmitting)
            {
                var w = new ChildWindow();
                w.Content = "The DomainContext still has unsaved changes.";
                w.Show();
            }
        }, null);
    }
}

public partial class MainPage : UserControl
{
    private void ClearCitiesEditRegion(object sender, RoutedEventArgs e)
    {
        var region = (RegionDto)regionList.SelectedItem;

        if (region != null)
        {
            region.Name += "*";
            while (region.Cities.Count > 0)
            {
                region.Cities.Remove(region.Cities.First());
            }

            CState.SaveChanges();
        }
    }

    private void ClearCities(object sender, RoutedEventArgs e)
    {
        var region = (RegionDto)regionList.SelectedItem;

        if (region != null)
        {
            while (region.Cities.Count > 0)
            {
                region.Cities.Remove(region.Cities.First());
            }

            CState.SaveChanges();
        }
    }
}

When you run this code the ChildWindow is only shown when you the ClearCitiesEditRegion() method is called. The only difference between this and the ClearCities() method is the line where I edit the region.Name property.

You can also download a sample project that reproduces this here: http://dl.dropbox.com/u/2393192/RIA_Services_Problem.zip

A: 

I received an answer to this on the Silverlight forums. Apparently this is a bug in RIA Service 1.0. The following is Matthew's response on the Silverlight forums.

Yes, I've confirmed this is a bug. Thanks for reporting it and providing the repro. As you discovered, the bug will only repro in composition scenarios where the parent has been modified in addition to one or more children. The workaround is to do an explicit AcceptChanges if the submit was successful. For example, here is the code you'd write in a submit callback:

   if (!submitOperation.HasError)
   {
      ((IChangeTracking)ctxt.EntityContainer).AcceptChanges();
   }

This will accept all changes and reset change state correctly.

Joshua Poehls