Question

I need to log changes made to an entity that occur on the client to a database table. However, when I make changes and inspect the ChangeTracker property, it claims that no changes have occurred.

[Service]

    private static readonly ISomeDao someDao = DataAccess.SomeDao;
    [Query]
    public List<SomeEntity> GetSomeEntites(int someId)
    {
        var entities = someDao.GetSomeEntites(someId);
        entities.ForEach(e => e.StartTracking());
        return entities;
    }

    [Update]
    public void UpdateSomeEntity(SomeEntity entity)
    {
        // inspect entity.ChangeTracker.OriginalValues.... nothing
        entity.StopTracking();
        // inspect entity.ChangeTracker.OriginalValues.... nothing
        ...
        // Update log table 
    }

[Client]

    public EntitySet<SomeEntity> SomeEntities
    {
        get { return _someEntity; }
        set
        {
            if (_someEntity!= value)
            {
                _someEntity= value;
                OnPropertyChanged("SomeEntities");
            }
        }
    }

So, if, self-tracking entities and WCF Ria Services can't live together (which is what I'm suspecting), how does one track changes?

Was it helpful?

Solution

Don't work with Ria services but solely with WCF (don't know if it makes much difference...). First of all you don't have to execute the command (server-side) to StartTracking the entities this is done automatically with deserializing by WCF.

[OnDeserialized]
public void OnDeserializedMethod(StreamingContext context)
{
  IsDeserializing = false;
  ChangeTracker.ChangeTrackingEnabled = true;
}

Second what I know is that only primary- and foreign key properties of a SELF tracking entity are recorded when changed. this is not the case for NORMAL entities that keep living in an entity context (then all changes are recorded).

If you take a closer look at a Self-Tracking-Entity you might see something like this:

    [DataMember]
    public string Plaats
    {
        get { return _plaats; }
        set
        {
            if (_plaats != value)
            {
                _plaats = value;
                OnPropertyChanged("Plaats");
            }
        }
    }
    private string _plaats;

    [DataMember]
    public int LandID
    {
        get { return _landID; }
        set
        {
            if (_landID != value)
            {
                ChangeTracker.RecordOriginalValue("LandID", _landID);
                if (!IsDeserializing)
                {
                    if (Land != null && Land.ID != value)
                    {
                        Land = null;
                    }
                }
                _landID = value;
                OnPropertyChanged("LandID");
            }
        }
    }
    private int _landID;

Do you see the difference? between the simple property Plaats and the Foreign key property LandID? It's in the line `ChangeTracker.RecordOriginalValue("LandID", _landID);

For simple properties these changes are not recorded (the properties themseklves are off-course changed, so that EF context knows how to ApplyChanges and update the database).

Possible ideas could be:

  1. To customize the T4 template to record original values for every property
  2. To derive all entities from a base class where you could lay down some framework for recording original values by responding to propertyChanged events
  3. When updating the entites, first getting the original values from the database and track the changes

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top