示例#1
0
        /// <summary>
        /// Attaches an entity to the DataContext in either a modified or unmodified state by specifying both the entity
        /// and its original state.
        /// </summary>
        /// <param name="entity">The entity to attach.</param>
        /// <param name="original">An instance of the same entity type with data members containing
        /// the original values.</param>
        public void Attach(TEntity entity, TEntity original)
        {
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            if (original == null)
            {
                throw Error.ArgumentNull("original");
            }
            if (entity.GetType() != original.GetType())
            {
                throw Error.OriginalEntityIsWrongType();
            }
            CheckReadOnly();
            context.CheckNotInSubmitChanges();
            context.VerifyTrackingEnabled();
            MetaType type = this.metaTable.RowType.GetInheritanceType(entity.GetType());

            if (type == null)
            {
                throw Error.InheritanceTypeNotRegistered(entity.GetType());
            }
            if (!IsTrackableType(type))
            {
                throw Error.TypeCouldNotBeTracked(type.Type);
            }
            TrackedObject tracked = this.context.Services.ChangeTracker.GetTrackedObject(entity);

            if (tracked == null || tracked.IsWeaklyTracked)
            {
                if (tracked == null)
                {
                    tracked = this.context.Services.ChangeTracker.Track(entity, true);
                }
                tracked.ConvertToPossiblyModified(original);
                if (this.Context.Services.InsertLookupCachedObject(type, entity) != entity)
                {
                    throw new DuplicateKeyException(entity, Strings.CantAddAlreadyExistingKey);
                }
                tracked.InitializeDeferredLoaders();
            }
            else
            {
                throw Error.CannotAttachAlreadyExistingEntity();
            }
        }
示例#2
0
        /// <summary>
        /// Adds an entity in a 'pending insert' state to this table.  The added entity will not be observed
        /// in query results from this table until after SubmitChanges() has been called.  Any untracked
        /// objects referenced directly or transitively by the entity will also be inserted.
        /// </summary>
        /// <param name="entity"></param>
        public void InsertOnSubmit(TEntity entity)
        {
            if (entity == null)
            {
                throw Error.ArgumentNull("entity");
            }
            CheckReadOnly();
            context.CheckNotInSubmitChanges();
            context.VerifyTrackingEnabled();
            MetaType type = this.metaTable.RowType.GetInheritanceType(entity.GetType());

            if (type == null)
            {
                throw Error.InheritanceTypeNotRegistered(entity.GetType());
            }
            if (!IsTrackableType(type))
            {
                throw Error.TypeCouldNotBeAdded(type.Type);
            }
            TrackedObject tracked = this.context.Services.ChangeTracker.GetTrackedObject(entity);

            if (tracked == null)
            {
                tracked = this.context.Services.ChangeTracker.Track(entity);
                tracked.ConvertToNew();
            }
            else if (tracked.IsWeaklyTracked)
            {
                tracked.ConvertToNew();
            }
            else if (tracked.IsDeleted)
            {
                tracked.ConvertToPossiblyModified();
            }
            else if (tracked.IsRemoved)
            {
                tracked.ConvertToNew();
            }
            else if (!tracked.IsNew)
            {
                throw Error.CantAddAlreadyExistingItem();
            }
        }
示例#3
0
        public void Attach(TEntity entity, TEntity original)
        {
            if ((object)entity == null)
            {
                throw System.Data.Linq.Error.ArgumentNull("entity");
            }
            if ((object)original == null)
            {
                throw System.Data.Linq.Error.ArgumentNull("original");
            }
            if (entity.GetType() != original.GetType())
            {
                throw System.Data.Linq.Error.OriginalEntityIsWrongType();
            }
            this.CheckReadOnly();
            this.context.CheckNotInSubmitChanges();
            this.context.VerifyTrackingEnabled();
            MetaType inheritanceType = this.metaTable.RowType.GetInheritanceType(entity.GetType());

            if (!Table <TEntity> .IsTrackableType(inheritanceType))
            {
                throw System.Data.Linq.Error.TypeCouldNotBeTracked((object)inheritanceType.Type);
            }
            TrackedObject trackedObject = this.context.Services.ChangeTracker.GetTrackedObject((object)entity);

            if (trackedObject != null && !trackedObject.IsWeaklyTracked)
            {
                throw System.Data.Linq.Error.CannotAttachAlreadyExistingEntity();
            }
            if (trackedObject == null)
            {
                trackedObject = this.context.Services.ChangeTracker.Track((object)entity, true);
            }
            trackedObject.ConvertToPossiblyModified((object)original);
            if (this.Context.Services.InsertLookupCachedObject(inheritanceType, (object)entity) != (object)entity)
            {
                throw new DuplicateKeyException((object)entity, System.Data.Linq.Strings.CantAddAlreadyExistingKey);
            }
            trackedObject.InitializeDeferredLoaders();
        }
示例#4
0
        public void InsertOnSubmit(TEntity entity)
        {
            if ((object)entity == null)
            {
                throw System.Data.Linq.Error.ArgumentNull("entity");
            }
            this.CheckReadOnly();
            this.context.CheckNotInSubmitChanges();
            this.context.VerifyTrackingEnabled();
            MetaType inheritanceType = this.metaTable.RowType.GetInheritanceType(entity.GetType());

            if (!Table <TEntity> .IsTrackableType(inheritanceType))
            {
                throw System.Data.Linq.Error.TypeCouldNotBeAdded((object)inheritanceType.Type);
            }
            TrackedObject trackedObject = this.context.Services.ChangeTracker.GetTrackedObject((object)entity);

            if (trackedObject == null)
            {
                this.context.Services.ChangeTracker.Track((object)entity).ConvertToNew();
            }
            else if (trackedObject.IsWeaklyTracked)
            {
                trackedObject.ConvertToNew();
            }
            else if (trackedObject.IsDeleted)
            {
                trackedObject.ConvertToPossiblyModified();
            }
            else if (trackedObject.IsRemoved)
            {
                trackedObject.ConvertToNew();
            }
            else if (!trackedObject.IsNew)
            {
                throw System.Data.Linq.Error.CantAddAlreadyExistingItem();
            }
        }
示例#5
0
        private void TrackUntrackedObjects(MetaType type, object item, Dictionary <object, object> visited)
        {
            if (!visited.ContainsKey(item))
            {
                visited.Add(item, item);
                TrackedObject tracked = this._tracker.GetTrackedObject(item);
                if (tracked == null)
                {
                    tracked = this._tracker.Track(item);
                    tracked.ConvertToNew();
                }
                else if (tracked.IsDead || tracked.IsRemoved)
                {
                    // ignore
                    return;
                }

                // search parents (objects we are dependent on)
                foreach (RelatedItem parent in this._services.GetParents(type, item))
                {
                    this.TrackUntrackedObjects(parent.Type, parent.Item, visited);
                }

                // synch up primary key
                if (tracked.IsNew)
                {
                    tracked.InitializeDeferredLoaders();

                    if (!tracked.IsPendingGeneration(tracked.Type.IdentityMembers))
                    {
                        tracked.SynchDependentData();
                        object cached = this._services.InsertLookupCachedObject(tracked.Type, item);
                        if (cached != item)
                        {
                            TrackedObject cachedTracked = this._tracker.GetTrackedObject(cached);
                            Debug.Assert(cachedTracked != null);
                            if (cachedTracked.IsDeleted || cachedTracked.CanInferDelete())
                            {
                                // adding new object with same ID as object being deleted.. turn into modified
                                tracked.ConvertToPossiblyModified(cachedTracked.Original);
                                // turn deleted to dead...
                                cachedTracked.ConvertToDead();

                                this._services.RemoveCachedObjectLike(tracked.Type, item);
                                this._services.InsertLookupCachedObject(tracked.Type, item);
                            }
                            else if (!cachedTracked.IsDead)
                            {
                                throw new DuplicateKeyException(item, Strings.CantAddAlreadyExistingKey);
                            }
                        }
                    }
                    else
                    {
                        // we may have a generated PK, however we set the PK on this new item to
                        // match a deleted item
                        object cached = this._services.GetCachedObjectLike(tracked.Type, item);
                        if (cached != null)
                        {
                            TrackedObject cachedTracked = this._tracker.GetTrackedObject(cached);
                            Debug.Assert(cachedTracked != null);
                            if (cachedTracked.IsDeleted || cachedTracked.CanInferDelete())
                            {
                                // adding new object with same ID as object being deleted.. turn into modified
                                tracked.ConvertToPossiblyModified(cachedTracked.Original);
                                // turn deleted to dead...
                                cachedTracked.ConvertToDead();

                                this._services.RemoveCachedObjectLike(tracked.Type, item);
                                this._services.InsertLookupCachedObject(tracked.Type, item);
                            }
                        }
                    }
                }

                // search children (objects that are dependent on us)
                foreach (RelatedItem child in this._services.GetChildren(type, item))
                {
                    this.TrackUntrackedObjects(child.Type, child.Item, visited);
                }
            }
        }