/// <summary> /// Internal method called by the StoreConflict class during RejectChangesInternal to resolve a store conflict /// without locking the the save sync lock. This ultimately filters down through CancelChanges, which locks, /// so this method does not need to. When it does lock, it causes a deadlock. /// </summary> /// <param name="conflict"></param> /// <param name="resolutionAction"></param> internal void ResolveStoreConflictNoLock(StoreConflict conflict, StoreConflictResolutionAction resolutionAction) { // Cache the modified entity, which may disappear depending on the resolution IsolatedStorageOfflineEntity visibleEntity = conflict.ModifiedEntity; // Respond to the resolution if (resolutionAction == StoreConflictResolutionAction.AcceptModifiedEntity) { ((IsolatedStorageOfflineEntity)conflict.ModifiedEntity).UpdateModifiedTickCount(); } else if (resolutionAction == StoreConflictResolutionAction.AcceptStoreEntity) { _cacheData.ResolveStoreConflictByRollback(conflict.ModifiedEntity); } else { throw new ArgumentException("Invalid resolution action specified"); } // Cleanup pointers to conflicts everywhere. visibleEntity.StoreConflict = null; this._storeConflicts.Remove(conflict); // Clearing the context will prevent the resolution from being triggered again. conflict.ClearContext(); }
public bool ContainsEntity(IsolatedStorageOfflineEntity entity) { // If the entity is a tombstone, use the atom id if (entity.IsTombstone) { if (String.IsNullOrEmpty(entity.ServiceMetadata.Id)) { // if it's a tombstone and the id is null, it means it is a delete of // a local insert that can be skipped, so we report it as already written return(true); } else { return(_atomIdSet.Contains(entity.ServiceMetadata.Id)); } } else { if (!String.IsNullOrEmpty(entity.ServiceMetadata.Id)) { return(_atomIdSet.Contains(entity.ServiceMetadata.Id)); } OfflineEntityKey key = entity.GetIdentity() as OfflineEntityKey; key.TypeName = entity.GetType().FullName; if (_pkeySet.Contains(key)) { return(true); } return(false); } }
public void ProcessedEntity(IsolatedStorageOfflineEntity entity) { string atomId = entity.ServiceMetadata.Id; OfflineEntityKey key = entity.GetIdentity() as OfflineEntityKey; key.TypeName = entity.GetType().FullName; if (entity.IsTombstone) { if (String.IsNullOrEmpty(atomId)) { _pkeySet.Add(key); } else { _atomIdSet.Add(atomId); } } else { _pkeySet.Add(key); if (!String.IsNullOrEmpty(atomId)) { _atomIdSet.Add(atomId); } } }
private void CollectionModifiedEntityChanged(IsolatedStorageOfflineEntity entity) { Action <IsolatedStorageOfflineEntity> action = ModifiedItemChanged; if (action != null) { action(entity); } }
protected void OnModifiedItemChanged(IsolatedStorageOfflineEntity changedEntity) { Action <IsolatedStorageOfflineEntity> action = ModifiedItemChanged; if (action != null) { action(changedEntity); } }
protected void OnModifiedItemChanged(IsolatedStorageOfflineEntity changedEntity) { Action<IsolatedStorageOfflineEntity> action = ModifiedItemChanged; if (action != null) { action(changedEntity); } }
/// <summary> /// Adds a new collection for the type T. /// </summary> /// <typeparam name="T">Type of entity for the new collection</typeparam> public void AddCollection <T>() where T : IsolatedStorageOfflineEntity { Type t = typeof(T); if (IsolatedStorageOfflineEntity.GetEntityKeyProperties(t).Length == 0) { throw new ArgumentException("Type: " + t.FullName + " does not have a key specified"); } _collections.Add(t.FullName, t); }
/// <summary> /// Adds a conflict to the list of in-memory /// </summary> /// <param name="conflict">Conflict to add</param> /// <param name="context">Context for which the conflict is being added</param> public void AddSyncConflict(SyncConflict conflict, IsolatedStorageOfflineContext context) { IsolatedStorageOfflineEntity entity = Collections[conflict.LiveEntity.GetType()].AddOrUpdateSyncEntity((IsolatedStorageOfflineEntity)conflict.LiveEntity); SyncConflict oldConflict = Collections[conflict.LiveEntity.GetType()].MapSyncConflict(entity, conflict, context); SyncConflicts.Add(conflict); if (oldConflict != null) { ClearSyncConflict(oldConflict, context); } }
/// <summary> /// Adds a error to the list of in-memory /// </summary> /// <param name="error"></param> /// <param name="context">Context for the conflict is being added</param> public void AddSyncError(SyncError error, IsolatedStorageOfflineContext context) { IsolatedStorageOfflineEntity entity = Collections[error.LiveEntity.GetType()].AddOrUpdateSyncEntity((IsolatedStorageOfflineEntity)error.LiveEntity); SyncError oldError = Collections[error.LiveEntity.GetType()].MapSyncError(entity, error, context); SyncErrors.Add(error); if (oldError != null) { ClearSyncError(oldError, context); } }
/// <summary> /// Does reflection to copy the properties from another entity to this entity /// </summary> /// <param name="entity">Entity from which to copy properties</param> private void CopyEntityToThis(IsolatedStorageOfflineEntity entity) { PropertyInfo[] propInfos = GetEntityProperties(); object [] parameters = new object[] {}; foreach (PropertyInfo propInfo in propInfos) { propInfo.GetSetMethod().Invoke(this, new object[] { propInfo.GetGetMethod().Invoke(entity, parameters) }); } CopyODataPropertiesToThis(entity); this._entityMetadata.IsTombstone = entity._entityMetadata.IsTombstone; }
/// <summary> /// Gets the original state of the entity at the time it was last Submitted. /// </summary> /// <returns>The original entity, if the entity has been modified, null otherwise.</returns> public IsolatedStorageOfflineEntity GetOriginal() { IsolatedStorageOfflineEntity original = null; lock (_syncRoot) { if (this.EntityState == OfflineEntityState.Modified && this._original != null) { original = (IsolatedStorageOfflineEntity)Activator.CreateInstance(this.GetType()); FillEntityFromSnapshot(original); original.IsReadOnly = true; } } return(original); }
/// <summary> /// Copies the properties from the entity to the snapshot /// </summary> /// <param name="entity">Entity from which to copy properties</param> private OfflineEntitySnapshot GetSnapshotFromEntity(IsolatedStorageOfflineEntity entity) { OfflineEntitySnapshot snapshot = new OfflineEntitySnapshot(); PropertyInfo[] properties = GetEntityProperties(); // Copy data properties foreach (PropertyInfo property in properties) { object val = property.GetGetMethod().Invoke(entity, null); snapshot.Properties[property.Name] = val; } snapshot.TickCount = entity.TickCount; snapshot.EntityState = entity.EntityState; snapshot.Metadata = entity.ServiceMetadata.Clone(); return(snapshot); }
/// <summary> /// Uses the snapshot to fill the entity's properties /// </summary> /// <param name="entity">Entity to fill</param> internal void FillEntityFromSnapshot(IsolatedStorageOfflineEntity entity) { Type type = entity.GetType(); foreach (var property in _original.Properties) { PropertyInfo propInfo = type.GetProperty(property.Key); // If propInfo is null, it's an internal property // that will be handled later if (propInfo != null) { propInfo.GetSetMethod().Invoke(entity, new object[] { property.Value }); } } // Get the internal properties entity._entityMetadata = _original.Metadata; entity.EntityState = _original.EntityState; entity.TickCount = _original.TickCount; }
/// <summary> /// Updates an entity from sync. /// </summary> /// <param name="entity">Entity with changes to update</param> /// <returns>Whether or not the entity is already modified</returns> internal void UpdateFromSync(IsolatedStorageOfflineEntity entity) { lock (_syncRoot) { if (this.EntityState == OfflineEntityState.Modified) { OfflineEntitySnapshot snapshot = GetSnapshotFromEntity(entity); snapshot.IsTombstone = entity.IsTombstone; snapshot.TickCount = this.TickCount + 1; this._original = snapshot; } else { _trackChanges = false; // Update properties CopyEntityToThis(entity); _trackChanges = true; } } }
public abstract void AddSerializedEntity(IsolatedStorageOfflineEntity entity);
public void ResolveStoreConflictByRollback(IsolatedStorageOfflineEntity entity) { }
public abstract void ResolveConflictByRollback(IsolatedStorageOfflineEntity entity);
public abstract void ClearSyncError(IsolatedStorageOfflineEntity entity);
/// <summary> /// Copies OData properties that don't need to be snapshoted /// </summary> /// <param name="entity">Entity from which to copy properties</param> private void CopyODataPropertiesToThis(IsolatedStorageOfflineEntity entity) { this._entityMetadata.Id = entity._entityMetadata.Id; this._entityMetadata.EditUri = entity._entityMetadata.EditUri; this._entityMetadata.ETag = entity._entityMetadata.ETag; }
public abstract SyncConflict MapSyncConflict(IsolatedStorageOfflineEntity entity, SyncConflict conflict, IsolatedStorageOfflineContext context);
public void AddSerializedDownloadItem(IsolatedStorageOfflineEntity entity) { entity.EntityState = OfflineEntityState.Unmodified; // Pass the entity to the collection Collections[entity.GetType()].AddOrUpdateSyncEntity(entity); }
/// <summary> /// Method called by the context to resolve a conflict with StoreItemWins /// </summary> /// <param name="entity"></param> public void ResolveStoreConflictByRollback(IsolatedStorageOfflineEntity entity) { Type type = entity.GetType(); Collections[type].ResolveConflictByRollback(entity); }
public void AddSerializedLocalChange(IsolatedStorageOfflineEntity entity) { entity.EntityState = OfflineEntityState.Saved; Collections[entity.GetType()].AddSerializedEntity(entity); }
/// <summary> /// Copies the properties from the entity to the snapshot /// </summary> /// <param name="entity">Entity from which to copy properties</param> private OfflineEntitySnapshot GetSnapshotFromEntity(IsolatedStorageOfflineEntity entity) { OfflineEntitySnapshot snapshot = new OfflineEntitySnapshot(); PropertyInfo[] properties = GetEntityProperties(); // Copy data properties foreach (PropertyInfo property in properties) { object val = property.GetGetMethod().Invoke(entity, null); snapshot.Properties[property.Name] = val; } snapshot.TickCount = entity.TickCount; snapshot.EntityState = entity.EntityState; snapshot.Metadata = entity.ServiceMetadata.Clone(); return snapshot; }
public abstract IsolatedStorageOfflineEntity AddOrUpdateSyncEntity(IsolatedStorageOfflineEntity entity);
public abstract void ClearSyncConflict(IsolatedStorageOfflineEntity entity);
/// <summary> /// Does reflection to copy the properties from another entity to this entity /// </summary> /// <param name="entity">Entity from which to copy properties</param> private void CopyEntityToThis(IsolatedStorageOfflineEntity entity) { PropertyInfo[] propInfos = GetEntityProperties(); object [] parameters = new object[]{}; foreach (PropertyInfo propInfo in propInfos) { propInfo.GetSetMethod().Invoke(this, new object[] { propInfo.GetGetMethod().Invoke(entity, parameters) }); } CopyODataPropertiesToThis(entity); this._entityMetadata.IsTombstone = entity._entityMetadata.IsTombstone; }
public abstract IsolatedStorageOfflineEntity AddOrUpdateSyncEntity(IsolatedStorageOfflineEntity entity, bool delayNotification);
public abstract SyncError MapSyncError(IsolatedStorageOfflineEntity entity, SyncError error, IsolatedStorageOfflineContext context);
public void AddSerializedLocalChange(IsolatedStorageOfflineEntity entity) { }
public void AddSerializedDownloadItem(IsolatedStorageOfflineEntity entity) { }