//End identical code

        /// <summary>
        /// Take any values in the incoming RelatedEnd and sets them onto the values
        /// that currently exist in this RelatedEnd
        /// </summary>
        /// <param name="rhs"></param>
        internal void InitializeWithValue(RelatedEnd relatedEnd)
        {
            Debug.Assert(this._wrappedCachedValue.Entity == null, "The EntityReference already has a value.");
            EntityReference <TEntity> reference = relatedEnd as EntityReference <TEntity>;

            if (reference != null && reference._wrappedCachedValue.Entity != null)
            {
                _wrappedCachedValue = reference._wrappedCachedValue;
                _cachedValue        = (TEntity)_wrappedCachedValue.Entity;
            }
        }
Пример #2
0
        /// <summary>
        /// Removes all entities from the locally cached collection.  Also removes
        /// relationships related to this entities from the ObjectStateManager.
        /// </summary>
        public void Clear()
        {
            DeferredLoad();
            if (WrappedOwner.Entity != null)
            {
                bool shouldFireEvent = (CountInternal > 0);
                if (null != _wrappedRelatedEntities)
                {
                    List <IEntityWrapper> affectedEntities = new List <IEntityWrapper>(_wrappedRelatedEntities.Values);

                    try
                    {
                        _suppressEvents = true;

                        foreach (IEntityWrapper wrappedEntity in affectedEntities)
                        {
                            // Remove Entity
                            Remove(wrappedEntity, false);

                            if (UsingNoTracking)
                            {
                                // The other end of relationship can be the EntityReference or EntityCollection
                                // If the other end is EntityReference, its IsLoaded property should be set to FALSE
                                RelatedEnd relatedEnd = GetOtherEndOfRelationship(wrappedEntity);
                                relatedEnd.OnRelatedEndClear();
                            }
                        }
                        Debug.Assert(_wrappedRelatedEntities.Count == 0);
                    }
                    finally
                    {
                        _suppressEvents = false;
                    }

                    if (UsingNoTracking)
                    {
                        _isLoaded = false;
                    }
                }

                if (shouldFireEvent)
                {
                    OnAssociationChanged(CollectionChangeAction.Refresh, null);
                }
            }
            else
            {
                // Disconnected Clear should be dispatched to the internal collection
                if (_wrappedRelatedEntities != null)
                {
                    _wrappedRelatedEntities.Clear();
                }
            }
        }
        private void IncludeEntityKey(bool doAttach)
        {
            ObjectStateManager manager = this.ObjectContext.ObjectStateManager;

            bool        addNewRelationship = false;
            bool        addKeyEntry        = false;
            EntityEntry existingEntry      = manager.FindEntityEntry(DetachedEntityKey);

            if (existingEntry == null)
            {
                // add new key entry and create a relationship with it
                addKeyEntry        = true;
                addNewRelationship = true;
            }
            else
            {
                if (existingEntry.IsKeyEntry)
                {
                    // We have an existing key entry, so just need to add a relationship with it

                    // We know the target end of this relationship is 1..1 or 0..1 since it is a reference, so if the source end is also not Many, we have a 1-to-1
                    if (FromEndProperty.RelationshipMultiplicity != RelationshipMultiplicity.Many)
                    {
                        // before we add a new relationship to this key entry, make sure it's not already related to something else
                        // We have to explicitly do this here because there are no other checks to make sure a key entry in a 1-to-1 doesn't end up in two of the same relationship
                        foreach (RelationshipEntry relationshipEntry in this.ObjectContext.ObjectStateManager.FindRelationshipsByKey(DetachedEntityKey))
                        {
                            // only care about relationships in the same AssociationSet and where the key is playing the same role that it plays in this EntityReference
                            if (relationshipEntry.IsSameAssociationSetAndRole((AssociationSet)RelationshipSet, (AssociationEndMember)ToEndMember, DetachedEntityKey) &&
                                relationshipEntry.State != EntityState.Deleted)
                            {
                                throw EntityUtil.EntityConflictsWithKeyEntry();
                            }
                        }
                    }

                    addNewRelationship = true;
                }
                else
                {
                    IEntityWrapper wrappedTarget = existingEntry.WrappedEntity;

                    // Verify that the target entity is in a valid state for adding a relationship
                    if (existingEntry.State == EntityState.Deleted)
                    {
                        throw EntityUtil.UnableToAddRelationshipWithDeletedEntity();
                    }

                    // We know the target end of this relationship is 1..1 or 0..1 since it is a reference, so if the source end is also not Many, we have a 1-to-1
                    RelatedEnd relatedEnd = wrappedTarget.RelationshipManager.GetRelatedEndInternal(RelationshipName, RelationshipNavigation.From);
                    if (FromEndProperty.RelationshipMultiplicity != RelationshipMultiplicity.Many && !relatedEnd.IsEmpty())
                    {
                        // Make sure the target entity is not already related to something else.
                        // devnote: The call to Add below does *not* do this check for the fixup case, so if it's not done here, no failure will occur
                        //          and existing relationships may be deleted unexpectedly. RelatedEnd.Include should not remove existing relationships, only add new ones.
                        throw EntityUtil.EntityConflictsWithKeyEntry();
                    }

                    // We have an existing entity with the same key, just hook up the related ends
                    this.Add(wrappedTarget,
                             applyConstraints: true,
                             addRelationshipAsUnchanged: doAttach,
                             relationshipAlreadyExists: false,
                             allowModifyingOtherEndOfRelationship: true,
                             forceForeignKeyChanges: true);

                    // add to the list of promoted key references so we can cleanup if a failure occurs later
                    manager.TransactionManager.PopulatedEntityReferences.Add(this);
                }
            }

            // For FKs, don't create a key entry and don't create a relationship
            if (addNewRelationship && !IsForeignKey)
            {
                // devnote: If we add any validation here, it needs to go here before adding the key entry,
                //          otherwise we have to clean up that entry if the validation fails

                if (addKeyEntry)
                {
                    EntitySet targetEntitySet = DetachedEntityKey.GetEntitySet(this.ObjectContext.MetadataWorkspace);
                    manager.AddKeyEntry(DetachedEntityKey, targetEntitySet);
                }

                EntityKey ownerKey = WrappedOwner.EntityKey;
                EntityUtil.CheckEntityKeyNull(ownerKey);
                RelationshipWrapper wrapper = new RelationshipWrapper((AssociationSet)RelationshipSet,
                                                                      RelationshipNavigation.From, ownerKey, RelationshipNavigation.To, DetachedEntityKey);
                manager.AddNewRelation(wrapper, doAttach ? EntityState.Unchanged : EntityState.Added);
            }
        }