Esempio n. 1
0
        /// <summary>
        /// Method called by proxy interceptor delegate to provide lazy loading behavior for navigation properties.
        /// </summary>
        /// <typeparam name="TItem">property type</typeparam>
        /// <param name="propertyValue">The property value whose associated relationship is to be loaded.</param>
        /// <param name="relationshipName">String name of the relationship.</param>
        /// <param name="targetRoleName">String name of the related end to be loaded for the relationship specified by <paramref name="relationshipName"/>.</param>
        /// <param name="wrapperObject">Entity wrapper object used to retrieve RelationshipManager for the proxied entity.</param>
        /// <returns>
        /// True if the value instance was mutated and can be returned
        /// False if the class should refetch the value because the instance has changed
        /// </returns>
        private static bool LoadProperty <TItem>(TItem propertyValue, string relationshipName, string targetRoleName, bool mustBeNull, object wrapperObject) where TItem : class
        {
            // Only attempt to load collection if:
            //
            // 1. Collection is non-null.
            // 2. ObjectContext.ContextOptions.LazyLoadingEnabled is true
            // 3. A non-null RelationshipManager can be retrieved (this is asserted).
            // 4. The EntityCollection is not already loaded.

            Debug.Assert(wrapperObject == null || wrapperObject is IEntityWrapper, "wrapperObject must be an IEntityWrapper");
            IEntityWrapper wrapper = (IEntityWrapper)wrapperObject; // We want an exception if the cast fails.

            if (wrapper != null && wrapper.Context != null)
            {
                RelationshipManager relationshipManager = wrapper.RelationshipManager;
                Debug.Assert(relationshipManager != null, "relationshipManager should be non-null");
                if (relationshipManager != null && (!mustBeNull || propertyValue == null))
                {
                    RelatedEnd relatedEnd = relationshipManager.GetRelatedEndInternal(relationshipName, targetRoleName);
                    relatedEnd.DeferredLoad();
                }
            }

            return(propertyValue != null);
        }
Esempio n. 2
0
        private static bool LoadProperty <TItem>(
            TItem propertyValue,
            string relationshipName,
            string targetRoleName,
            bool mustBeNull,
            object wrapperObject)
            where TItem : class
        {
            IEntityWrapper entityWrapper = (IEntityWrapper)wrapperObject;

            if (entityWrapper != null && entityWrapper.Context != null)
            {
                RelationshipManager relationshipManager = entityWrapper.RelationshipManager;
                if (relationshipManager != null && (!mustBeNull || (object)propertyValue == null))
                {
                    relationshipManager.GetRelatedEndInternal(relationshipName, targetRoleName).DeferredLoad();
                }
            }
            return((object)propertyValue != null);
        }
Esempio n. 3
0
        //"doFixup" equals to False is called from EntityCollection & Ref code only
        internal void Delete(bool doFixup)
        {
            ValidateState();

            if (doFixup)
            {
                if (State != EntityState.Deleted) //for deleted ObjectStateEntry its a no-op
                {
                    //Find two ends of the relationship
                    var entry1         = _cache.GetEntityEntry((EntityKey)GetCurrentRelationValue(0));
                    var wrappedEntity1 = entry1.WrappedEntity;
                    var entry2         = _cache.GetEntityEntry((EntityKey)GetCurrentRelationValue(1));
                    var wrappedEntity2 = entry2.WrappedEntity;

                    // If one end of the relationship is a KeyEntry, entity1 or entity2 is null.
                    // It is not possible that both ends of relationship are KeyEntries.
                    if (wrappedEntity1.Entity != null &&
                        wrappedEntity2.Entity != null)
                    {
                        // Obtain the ro role name and relationship name
                        // We don't create a full NavigationRelationship here because that would require looking up
                        // additional information like property names that we don't need.
                        var endMembers       = _relationshipWrapper.AssociationEndMembers;
                        var toRole           = endMembers[1].Name;
                        var relationshipName = ((AssociationSet)_entitySet).ElementType.FullName;
                        wrappedEntity1.RelationshipManager.RemoveEntity(toRole, relationshipName, wrappedEntity2);
                    }
                    else
                    {
                        // One end of relationship is a KeyEntry, figure out which one is the real entity and get its RelationshipManager
                        // so we can update the DetachedEntityKey on the EntityReference associated with this relationship
                        EntityKey           targetKey           = null;
                        RelationshipManager relationshipManager = null;
                        if (wrappedEntity1.Entity == null)
                        {
                            targetKey           = entry1.EntityKey;
                            relationshipManager = wrappedEntity2.RelationshipManager;
                        }
                        else
                        {
                            targetKey           = entry2.EntityKey;
                            relationshipManager = wrappedEntity1.RelationshipManager;
                        }
                        Debug.Assert(relationshipManager != null, "Entity wrapper returned a null RelationshipManager");

                        // Clear the detachedEntityKey as well. In cases where we have to fix up the detachedEntityKey, we will not always be able to detect
                        // if we have *only* a Deleted relationship for a given entity/relationship/role, so clearing this here will ensure that
                        // even if no other relationships are added, the key value will still be correct and we won't accidentally pick up an old value.

                        // devnote: Since we know the target end of this relationship is a key entry, it has to be a reference, so just cast
                        var targetMember    = RelationshipWrapper.GetAssociationEndMember(targetKey);
                        var entityReference =
                            (EntityReference)
                            relationshipManager.GetRelatedEndInternal(targetMember.DeclaringType.FullName, targetMember.Name);
                        entityReference.DetachedEntityKey = null;

                        // Now update the state
                        if (State == EntityState.Added)
                        {
                            // Remove key entry if necessary
                            DeleteUnnecessaryKeyEntries();
                            // Remove relationship entry
                            // devnote: Using this method instead of just changing the state because the entry
                            //          may have already been detached along with the key entry above. However,
                            //          if there were other relationships using the key, it would not have been deleted.
                            DetachRelationshipEntry();
                        }
                        else
                        {
                            // Non-added entries should be deleted
                            _cache.ChangeState(this, State, EntityState.Deleted);
                            State = EntityState.Deleted;
                        }
                    }
                }
            }
            else
            {
                switch (State)
                {
                case EntityState.Added:
                    // Remove key entry if necessary
                    DeleteUnnecessaryKeyEntries();
                    // Remove relationship entry
                    // devnote: Using this method instead of just changing the state because the entry
                    //          may have already been detached along with the key entry above. However,
                    //          if there were other relationships using the key, it would not have been deleted.
                    DetachRelationshipEntry();
                    break;

                case EntityState.Modified:
                    Debug.Assert(false, "RelationshipEntry cannot be in Modified state");
                    break;

                case EntityState.Unchanged:
                    _cache.ChangeState(this, EntityState.Unchanged, EntityState.Deleted);
                    State = EntityState.Deleted;
                    break;
                    //case DataRowState.Deleted:  no-op
                }
            }
        }