/// <summary> /// Builds the list of submit operations from the current <see cref="EntityChangeSet"/>. /// </summary> /// <param name="changeSet">The <see cref="EntityChangeSet"/> to process.</param> /// <returns>The list of <see cref="ChangeSetEntry"/> for the specified <see cref="EntityChangeSet"/>.</returns> private static List<ChangeSetEntry> BuildOperations(EntityChangeSet changeSet) { List<ChangeSetEntry> operations = new List<ChangeSetEntry>(); int clientID = 0; EntityOperationType operationType = EntityOperationType.None; foreach (Entity entity in changeSet) { switch (entity.EntityState) { case EntityState.New: operationType = EntityOperationType.Insert; break; case EntityState.Modified: operationType = EntityOperationType.Update; break; case EntityState.Deleted: operationType = EntityOperationType.Delete; break; default: continue; } // create the operation and apply any original values ChangeSetEntry changeSetEntry = new ChangeSetEntry(entity, clientID++, operationType); if (entity.OriginalValues != null) { if (entity.MetaType.ShouldRoundtripOriginal && entity.OriginalValues != null) { changeSetEntry.OriginalEntity = GetRoundtripEntity(entity); } else { // In cases where the entity is modified but we're not sending // an original we need to flag the entity as having changes. // For example, this happens in Timestamp scenarios. changeSetEntry.HasMemberChanges = true; } } // add any custom method invocations if (entity.CustomMethodInvocation != null) { if (string.IsNullOrEmpty(entity.CustomMethodInvocation.Name)) { throw new ArgumentException(Resource.DomainClient_InvocationNameCannotBeNullOrEmpty); } if (changeSetEntry.EntityActions == null) { changeSetEntry.EntityActions = new Dictionary<string, object[]>(); } changeSetEntry.EntityActions.Add(entity.CustomMethodInvocation.Name, entity.CustomMethodInvocation.Parameters.ToArray()); } operations.Add(changeSetEntry); } return operations; }
/// <summary> /// Build and set the association maps for all operations in the specified changeset /// </summary> private void Build() { foreach (var entityGroup in this._changeSetEntries.GroupBy(p => p.Entity.GetType())) { foreach (ChangeSetEntry changeSetEntry in entityGroup) { this._currentChangeSetEntry = changeSetEntry; this.Visit(changeSetEntry.Entity); } } }
public override void Visit(Entity entity) { if (this._visited.ContainsKey(entity)) { return; } // if the entity is unmodified, add an ChangeSetEntry for it if (this._isChild && entity.EntityState == EntityState.Unmodified) { ChangeSetEntry op = new ChangeSetEntry(entity, this._id++, EntityOperationType.None); this._changeSetEntries.Add(op); } this._visited.Add(entity, true); base.Visit(entity); }
/// <summary> /// Builds the list of submit operations from the current <see cref="EntityChangeSet"/>. /// </summary> /// <param name="changeSet">The <see cref="EntityChangeSet"/> to process.</param> /// <returns>The list of <see cref="ChangeSetEntry"/> for the specified <see cref="EntityChangeSet"/>.</returns> private static List <ChangeSetEntry> BuildOperations(EntityChangeSet changeSet) { List <ChangeSetEntry> operations = new List <ChangeSetEntry>(); int clientID = 0; EntityOperationType operationType = EntityOperationType.None; foreach (Entity entity in changeSet) { switch (entity.EntityState) { case EntityState.New: operationType = EntityOperationType.Insert; break; case EntityState.Modified: operationType = EntityOperationType.Update; break; case EntityState.Deleted: operationType = EntityOperationType.Delete; break; default: continue; } // create the operation and apply any original values ChangeSetEntry changeSetEntry = new ChangeSetEntry(entity, clientID++, operationType); if (entity.OriginalValues != null) { if (entity.MetaType.ShouldRoundtripOriginal && entity.OriginalValues != null) { changeSetEntry.OriginalEntity = GetRoundtripEntity(entity); } else { // In cases where the entity is modified but we're not sending // an original we need to flag the entity as having changes. // For example, this happens in Timestamp scenarios. changeSetEntry.HasMemberChanges = true; } } // add any custom method invocations var entityActions = (ICollection <EntityAction>)entity.EntityActions; foreach (EntityAction customInvokation in entityActions) { if (string.IsNullOrEmpty(customInvokation.Name)) { throw new ArgumentException(Resource.DomainClient_InvocationNameCannotBeNullOrEmpty); } if (changeSetEntry.EntityActions == null) { changeSetEntry.EntityActions = new List <Serialization.KeyValue <string, object[]> >(); } changeSetEntry.EntityActions.Add( new Serialization.KeyValue <string, object[]>(customInvokation.Name, customInvokation.Parameters.ToArray())); } operations.Add(changeSetEntry); } return(operations); }
protected override void VisitEntityRef(IEntityRef entityRef, Entity parent, MetaMember member) { // Check for [ExternalReference] properties, if found we can skip visiting these // external entities so they will not be included in our change set. if (member.IsExternalReference) { return; } // We don't want to cause any deferred loading of the EntityRef in non-compositional // cases. Note that the UnmodifiedOperationAdder has already caused compositional // associations to load, so they will have values. Entity referenced = null; if (entityRef != null && entityRef.HasValue) { referenced = entityRef.Entity; } // Now determine the originally referenced entity if this association is a composition // and the child has been removed Entity prevReferenced = null; bool isComposition = member.IsComposition; if (isComposition && parent.EntityState != EntityState.New) { ChangeSetEntry entry = this.FindOriginalChildren(member.AssociationAttribute).SingleOrDefault(); if (entry != null) { prevReferenced = entry.Entity; } } if (isComposition && prevReferenced == null) { // if this is an unmodified composition, set the previously referenced entity // to the currently referenced entity prevReferenced = referenced; } // If the referenced entity is New and the parent is not Deleted or the referenced entity is a composed child and the target // is part of the changeset, set the association int refId = -1; bool shouldIncludeNewAssociation = referenced != null && (this._currentChangeSetEntry.Entity.EntityState != EntityState.Deleted && referenced.EntityState == EntityState.New); if (referenced != null && (shouldIncludeNewAssociation || isComposition) && this._entityIdMap.TryGetValue(referenced, out refId)) { // set the current reference Dictionary <string, int[]> associatedEntities = (Dictionary <string, int[]>) this._currentChangeSetEntry.Associations; if (associatedEntities == null) { associatedEntities = new Dictionary <string, int[]>(); this._currentChangeSetEntry.Associations = associatedEntities; } associatedEntities.Add(member.Name, new int[] { refId }); } // If the association is a composition, set the original reference if (prevReferenced != null && isComposition && this._entityIdMap.TryGetValue(prevReferenced, out refId)) { Dictionary <string, int[]> associatedEntities = (Dictionary <string, int[]>) this._currentChangeSetEntry.OriginalAssociations; if (associatedEntities == null) { associatedEntities = new Dictionary <string, int[]>(); this._currentChangeSetEntry.OriginalAssociations = associatedEntities; } associatedEntities.Add(member.Name, new int[] { refId }); } }