SaveChanges() losing changes, not applying changes to database

5 posts, 0 answers
  1. Roger
    Roger avatar
    32 posts
    Member since:
    Feb 2009

    Posted 04 Nov 2010 Link to this post

    I'm using the new domain model for my application, and so far I like it.  I'm having a huge problem right now, though, where it appears that data is getting lost on the update.

    I'm using the DataManager class that Telerik provides.  My update service call looks like this:

    public void UpdatePattern(Pattern modelPattern)
    {
        using (var context = new DataManager(new DAL.MyContext()))
        {
            var dataPattern = new DAL.Pattern { ModifiedDate = DateTime.Now };
     
            this.MapPatternModelToData(modelPattern, dataPattern);
     
            context.UpdateEntity(dataPattern);
        }
    }

    The Telerik code for UpdateEntity looks like this:

    public string UpdateEntity<T>(T entity)
    {
        try
        {
            IObjectId id = Database.OID.GetObjectId(entity);
            T existingEntity = _openAccessContext.GetObject<T>(new ObjectKey(id));
            this.ExecuteCopy(entity, existingEntity);
            this._openAccessContext.SaveChanges();
     
            return id.ToString();
        }
        catch (OpenAccessException)
        {
            this._openAccessContext.ClearChanges();
            throw;
        }
    }

    The ExecuteCopy() method is correctly copying the data to the 'existingEntity' but somehow SaveChanges() is dropping the changes on the way to the database.  For example, I had changed the value of TypeId but, as you can tell from my profiler, the TypeId (@p5) is set to NULL:

    declare @p1 int
    set @p1=7
    exec sp_prepexec @p1 output,N'@p0 int,@p1 datetime,@p2 int,@p3 int,@p4 int,@p5 int,@p6 uniqueidentifier,@p7 int,@p8 uniqueidentifier',N'UPDATE [Pattern] SET [Measurement1Id]=@p0, [ModifiedDate]=@p1, [Measurement2Id]=@p2, [RangeId]=@p3, [FeatureId]=@p4, [TypeId]=@p5, [UniqueId]=@p6 WHERE [PatternId] = @p7 AND [Measurement2Id] is null AND [Measurement1Id] is null AND [RangeId] is null AND [FeatureId] is null AND [TypeId] is null AND [UniqueId]=@p8',@p0=NULL,@p1='2010-11-04 08:13:43:993',@p2=NULL,@p3=NULL,@p4=NULL,@p5=NULL,@p6='00000000-0000-0000-0000-000000000000',@p7=10,@p8='91958B38-DE5A-4E5A-B763-5316EB4EBB7D'
    select @p1

    What would cause this to happen?
  2. Roger
    Roger avatar
    32 posts
    Member since:
    Feb 2009

    Posted 04 Nov 2010 Link to this post

    Looking at it a little further, I can guess that it has something to do with the persistent entity that is generated with it.  Since I am only setting the FK ID for that entity, and the persistent entity is null, the call is using the null entity instead of the FK ID that I'm providing.  But it seems to me that, using the old methods (e.g. IObjectScope), a Commit() would look at both the FK ID and the entity and decide to take the one that had data.  Is that impression wrong?

    So, if my deduction here is correct, what's the proper way to attach the persistent entity, given the FK ID?
  3. DevCraft banner
  4. Jan Blessenohl
    Admin
    Jan Blessenohl avatar
    707 posts

    Posted 04 Nov 2010 Link to this post

    Hi Roger,
    What is executecopy doing? If you copy the values directly into the fields via reflection it will not work because we cannot make the object dirty.

    Best wishes,
    Jan Blessenohl
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  5. Roger
    Roger avatar
    32 posts
    Member since:
    Feb 2009

    Posted 04 Nov 2010 Link to this post

    ExecuteCopy() is part of the DataManager class that the DSW produces (though I'm not using the DSW).  As you say, it copies directly into the fields via reflection, but it copies into an enhanced object--the object is retrieved using the OpenAccessDataContextBase.GetObject<T>(ObjectKey) method--so it looks like IsDirty is getting set correctly.

    How can I tell if an object is enhanced?  Is there something like a GetIsPersisted() method or IsEnhanced property that can be called on an entity?

    And my original question still stands:  Why doesn't the data context notice that a change has occurred on the ID field and use that, instead of defaulting to the null entity field?
  6. A.Alexandrov
    Admin
    A.Alexandrov avatar
    25 posts

    Posted 16 Nov 2010 Link to this post

    Hi Roger,

    Unfortunately we were unable to reproduce the problem on our side. At this stage I will have to ask you to send us your project so we can debug it locally.
    Regarding the ExecuteCopy method, this should not be the problem. It updates the object's properties, which on their side set the dirty flag to true. You can verify this using the following code:
     
    var result = obj.GetType().GetMethod("OpenAccessEnhancedIsDirty").Invoke(obj, new object[] { propertyName });
    where propertyName is the name of the property that you want to check before calling SaveChanges().

    Kind regards,
    A.Alexandrov
    the Telerik team
    See What's New in Telerik OpenAccess ORM in Q3 2010!
    Monday, November 15, 11 am Eastern Time: Register here>>
    Monday, November 15, 10 pm Eastern Time: Register here>>
Back to Top
DevCraft banner