Esempio n. 1
0
 internal DeferredSourceFactory(MetaDataMember member, CommonDataServices services)
 {
     this.member             = member;
     this.services           = services;
     this.refersToPrimaryKey = this.member.IsAssociation && this.member.Association.OtherKeyIsPrimaryKey;
     this.empty = new T[] { };
 }
Esempio n. 2
0
 private bool HasAssociationChanged(MetaAssociation assoc, TrackedObject item)
 {
     if (item.Original != null && item.Current != null)
     {
         if (assoc.ThisMember.StorageAccessor.HasAssignedValue(item.Current) ||
             assoc.ThisMember.StorageAccessor.HasLoadedValue(item.Current)
             )
         {
             return(this.GetOtherItem(assoc, item.Current) != this.GetOtherItem(assoc, item.Original));
         }
         else
         {
             object[] currentFKs = CommonDataServices.GetForeignKeyValues(assoc, item.Current);
             object[] originaFKs = CommonDataServices.GetForeignKeyValues(assoc, item.Original);
             for (int i = 0, n = currentFKs.Length; i < n; i++)
             {
                 if (!object.Equals(currentFKs[i], originaFKs[i]))
                 {
                     return(true);
                 }
             }
         }
     }
     return(false);
 }
Esempio n. 3
0
        private void Init(object connection, MappingSource mapping)
        {
            _perInstanceProviderMode = DataContext.ProviderMode;
            MetaModel model = mapping.GetModel(this.GetType());

            this._services  = new CommonDataServices(this, model);
            this._conflicts = new ChangeConflictCollection();

            // determine provider
            Type providerType;

            if (model.ProviderType != null)
            {
                providerType = model.ProviderType;
            }
            else
            {
                throw Error.ProviderTypeNull();
            }

            if (!typeof(IProvider).IsAssignableFrom(providerType))
            {
                throw Error.ProviderDoesNotImplementRequiredInterface(providerType, typeof(IProvider));
            }

            this._provider = (IProvider)Activator.CreateInstance(providerType);
            SetProviderMode();
            this._provider.Initialize(this._services, connection);

            this._tables = new Dictionary <MetaTable, ITable>();
            this.InitTables(this);
        }
Esempio n. 4
0
 private void ClearForeignKeyReferences(TrackedObject to)
 {
     foreach (var association in to.Type.Associations)
     {
         if (association.IsForeignKey)
         {
             if (association.OtherMember != null && association.OtherKeyIsPrimaryKey)
             {
                 var foreignKeyValues = CommonDataServices.GetForeignKeyValues(association, to.Current);
                 var instance         = services.IdentityManager.Find(association.OtherType, foreignKeyValues);
                 if (instance != null)
                 {
                     if (association.OtherMember.Association.IsMany)
                     {
                         var list = association.OtherMember.MemberAccessor.GetBoxedValue(instance) as IList;
                         if (list != null && !list.IsFixedSize)
                         {
                             list.Remove(to.Current);
                             ClearForeignKeysHelper(association, to.Current);
                         }
                     }
                     else
                     {
                         association.OtherMember.MemberAccessor.SetBoxedValue(ref instance, null);
                         ClearForeignKeysHelper(association, to.Current);
                     }
                 }
             }
             else
             {
                 ClearForeignKeysHelper(association, to.Current);
             }
         }
     }
 }
Esempio n. 5
0
        private void Init(object connection, MappingSource mapping)
        {
            var model = mapping.GetModel(GetType());

            services  = new CommonDataServices(this, model);
            conflicts = new ChangeConflictCollection();

            // determine provider
            if (model.ProviderType == null)
            {
                throw Error.ProviderTypeNull();
            }
            var providerType = model.ProviderType;

            if (!typeof(IProvider).IsAssignableFrom(providerType))
            {
                throw Error.ProviderDoesNotImplementRequiredInterface(providerType, typeof(IProvider));
            }

            provider = (IProvider)Activator.CreateInstance(providerType);
            provider.Initialize(services, connection);

            tables = new Dictionary <MetaTable, ITable>();
            InitTables(this);
        }
Esempio n. 6
0
 internal static ChangeTracker CreateChangeTracker(CommonDataServices dataServices, bool asReadOnly)
 {
     if (asReadOnly)
     {
         return(new ReadOnlyChangeTracker());
     }
     return(new StandardChangeTracker(dataServices));
 }
Esempio n. 7
0
        /// <summary>
        /// Clears out the foreign key values and parent object references for deleted objects on the child side of a relationship.
        /// For bi-directional relationships, also performs the following fixup:
        ///   - for 1:N we remove the deleted entity from the opposite EntitySet or collection
        ///   - for 1:1 we null out the back reference
        /// </summary>
        private void ClearForeignKeyReferences(TrackedObject to)
        {
            Debug.Assert(to.IsDeleted, "Foreign key reference cleanup should only happen on Deleted objects.");
            foreach (MetaAssociation assoc in to.Type.Associations)
            {
                if (assoc.IsForeignKey)
                {
                    // If there is a member on the other side referring back to us (i.e. this is a bi-directional relationship),
                    // we want to do a cache lookup to find the other side, then will remove ourselves from that collection.
                    // This cache lookup is only possible if the other key is the primary key, since that is the only way items can be found in the cache.
                    if (assoc.OtherMember != null && assoc.OtherKeyIsPrimaryKey)
                    {
                        Debug.Assert(assoc.OtherMember.IsAssociation, "OtherMember of the association is expected to also be an association.");
                        // Search the cache for the target of the association, since
                        // it might not be loaded on the object being deleted, and we
                        // don't want to force a load.
                        object[] keyValues = CommonDataServices.GetForeignKeyValues(assoc, to.Current);
                        object   cached    = this._services.IdentityManager.Find(assoc.OtherType, keyValues);

                        if (cached != null)
                        {
                            if (assoc.OtherMember.Association.IsMany)
                            {
                                // Note that going through the IList interface handles
                                // EntitySet as well as POCO collections that implement IList
                                // and are not FixedSize.
                                System.Collections.IList collection = assoc.OtherMember.MemberAccessor.GetBoxedValue(cached) as System.Collections.IList;
                                if (collection != null && !collection.IsFixedSize)
                                {
                                    collection.Remove(to.Current);
                                    // Explicitly clear the foreign key values and parent object reference
                                    ClearForeignKeysHelper(assoc, to.Current);
                                }
                            }
                            else
                            {
                                // Null out the other association.  Since this is a 1:1 association,
                                // we're not concerned here with causing a deferred load, since the
                                // target is already cached (since we're deleting it).
                                assoc.OtherMember.MemberAccessor.SetBoxedValue(ref cached, null);
                                // Explicitly clear the foreign key values and parent object reference
                                ClearForeignKeysHelper(assoc, to.Current);
                            }
                        }
                        // else the item was not found in the cache, so there is no fixup that has to be done
                        // We are explicitly not calling ClearForeignKeysHelper because it breaks existing shipped behavior and we want to maintain backward compatibility
                    }
                    else
                    {
                        // This is a unidirectional relationship or we have no way to look up the other side in the cache, so just clear our own side
                        ClearForeignKeysHelper(assoc, to.Current);
                    }
                }
                // else this is not the 1-side (foreign key) of the relationship, so there is nothing for us to do
            }
        }
Esempio n. 8
0
 internal ChangeProcessor(CommonDataServices services, DataContext context)
 {
     this._services                = services;
     this._context                 = context;
     this._tracker                 = services.ChangeTracker;
     this._changeDirector          = services.ChangeDirector;
     this._currentParentEdges      = new EdgeMap();
     this._originalChildEdges      = new EdgeMap();
     this._originalChildReferences = new ReferenceMap();
 }
Esempio n. 9
0
        /// <summary>
        /// Refresh a collection of objects using the mode specified.  If the refresh
        /// cannot be performed (for example if the object no longer exists in the
        /// database) an InvalidOperationException is thrown.
        /// </summary>
        /// <param name="mode">How the refresh should be performed.</param>
        /// <param name="entities">The collection of objects to refresh.</param>
        public void Refresh(RefreshMode mode, IEnumerable entities)
        {
            CheckDispose();
            CheckNotInSubmitChanges();
            VerifyTrackingEnabled();

            if (entities == null)
            {
                throw Error.ArgumentNull("entities");
            }

            // if the collection is a query, we need to execute and buffer,
            // since below we will be issuing additional queries and can only
            // have a single reader open.
            var list = entities.Cast <object>().ToList();

            // create a fresh context to fetch new state from
            DataContext refreshContext = this.CreateRefreshContext();

            foreach (object o in list)
            {
                // verify that each object in the list is an entity
                MetaType inheritanceRoot = _services.Model.GetMetaType(o.GetType()).InheritanceRoot;
                GetTable(inheritanceRoot.Type);

                TrackedObject trackedObject = this._services.ChangeTracker.GetTrackedObject(o);
                if (trackedObject == null)
                {
                    throw Error.UnrecognizedRefreshObject();
                }

                if (trackedObject.IsNew)
                {
                    throw Error.RefreshOfNewObject();
                }

                // query to get the current database values
                object[] keyValues     = CommonDataServices.GetKeyValues(trackedObject.Type, trackedObject.Original);
                object   freshInstance = refreshContext.Services.GetObjectByKey(trackedObject.Type, keyValues);
                if (freshInstance == null)
                {
                    throw Error.RefreshOfDeletedObject();
                }

                // refresh the tracked object using the new values and
                // the mode specified.
                trackedObject.Refresh(mode, freshInstance);
            }
        }
Esempio n. 10
0
        // Not implementing finalizer here because there are no unmanaged resources
        // to release. See http://msdnwiki.microsoft.com/en-us/mtpswiki/12afb1ea-3a17-4a3f-a1f0-fcdb853e2359.aspx

        // The bulk of the clean-up code is implemented in Dispose(bool)
        protected virtual void Dispose(bool disposing)
        {
            // Implemented but empty so that derived contexts can implement
            // a finalizer that potentially cleans up unmanaged resources.
            if (disposing)
            {
                if (this._provider != null)
                {
                    this._provider.Dispose();
                    this._provider = null;
                }
                this._services    = null;
                this._tables      = null;
                this._loadOptions = null;
            }
        }
Esempio n. 11
0
 private bool HasAssociationChanged(MetaAssociation assoc, TrackedObject item)
 {
     if (item.Original != null && item.Current != null)
     {
         if (assoc.ThisMember.StorageAccessor.HasAssignedValue(item.Current) || assoc.ThisMember.StorageAccessor.HasLoadedValue(item.Current))
         {
             return(GetOtherItem(assoc, item.Current) != GetOtherItem(assoc, item.Original));
         }
         var foreignKeyValues  = CommonDataServices.GetForeignKeyValues(assoc, item.Current);
         var foreignKeyValues2 = CommonDataServices.GetForeignKeyValues(assoc, item.Original);
         var i = 0;
         for (var num = foreignKeyValues.Length; i < num; i++)
         {
             if (!object.Equals(foreignKeyValues[i], foreignKeyValues2[i]))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Esempio n. 12
0
        private TrackedObject GetOtherItem(MetaAssociation assoc, object instance)
        {
            if (instance == null)
            {
                return(null);
            }
            object obj = null;

            if (assoc.ThisMember.StorageAccessor.HasAssignedValue(instance) || assoc.ThisMember.StorageAccessor.HasLoadedValue(instance))
            {
                obj = assoc.ThisMember.MemberAccessor.GetBoxedValue(instance);
            }
            else if (assoc.OtherKeyIsPrimaryKey)
            {
                var foreignKeyValues = CommonDataServices.GetForeignKeyValues(assoc, instance);
                obj = services.GetCachedObject(assoc.OtherType, foreignKeyValues);
            }
            if (obj == null)
            {
                return(null);
            }
            return(tracker.GetTrackedObject(obj));
        }
Esempio n. 13
0
        private TrackedObject GetOtherItem(MetaAssociation assoc, object instance)
        {
            if (instance == null)
            {
                return(null);
            }
            object other = null;

            // Don't load unloaded references
            if (assoc.ThisMember.StorageAccessor.HasAssignedValue(instance) ||
                assoc.ThisMember.StorageAccessor.HasLoadedValue(instance)
                )
            {
                other = assoc.ThisMember.MemberAccessor.GetBoxedValue(instance);
            }
            else if (assoc.OtherKeyIsPrimaryKey)
            {
                // Maybe it's in the cache, but not yet attached through reference.
                object[] foreignKeys = CommonDataServices.GetForeignKeyValues(assoc, instance);
                other = this._services.GetCachedObject(assoc.OtherType, foreignKeys);
            }
            // else the other key is not the primary key so there is no way to try to look it up
            return((other != null) ? this._tracker.GetTrackedObject(other) : null);
        }
Esempio n. 14
0
 internal StandardChangeTracker(CommonDataServices services)
 {
     this.services           = services;
     this.items              = new Dictionary <object, StandardTrackedObject>();
     this.onPropertyChanging = new PropertyChangingEventHandler(this.OnPropertyChanging);
 }
Esempio n. 15
0
 internal StandardChangeTracker(CommonDataServices services)
 {
     this.services      = services;
     items              = new Dictionary <object, StandardTrackedObject>();
     onPropertyChanging = OnPropertyChanging;
 }