Esempio n. 1
0
        protected virtual void Merge(Object obj, Object clone, MergeHandle handle)
        {
            IEntityMetaDataProvider entityMetaDataProvider = this.EntityMetaDataProvider;
            IEntityMetaData         metaData = ((IEntityMetaDataHolder)obj).Get__EntityMetaData();

            bool fieldBasedMergeActive = handle.FieldBasedMergeActive;
            bool oneChangeOccured      = false;

            try
            {
                RelationMember[] relationMembers = metaData.RelationMembers;
                if (relationMembers.Length > 0)
                {
                    IObjRefContainer vhc = (IObjRefContainer)obj;
                    for (int relationIndex = relationMembers.Length; relationIndex-- > 0;)
                    {
                        RelationMember relationMember = relationMembers[relationIndex];
                        if (!metaData.IsMergeRelevant(relationMember))
                        {
                            continue;
                        }
                        if (ValueHolderState.INIT != vhc.Get__State(relationIndex))
                        {
                            // v2 valueholder is not initialized. so a change is impossible
                            continue;
                        }
                        Object objMember   = relationMember.GetValue(obj, false);
                        Object cloneMember = relationMember.GetValue(clone, false);
                        if (objMember is IDataObject && !((IDataObject)objMember).HasPendingChanges)
                        {
                            IEntityMetaData relationMetaData = entityMetaDataProvider.GetMetaData(relationMember.RealType);
                            if (EqualsReferenceOrId(objMember, cloneMember, handle, relationMetaData))
                            {
                                continue;
                            }
                        }

                        IEntityMetaData childMetaData = entityMetaDataProvider.GetMetaData(relationMember.ElementType);

                        if (IsMemberModified(objMember, cloneMember, handle, childMetaData))
                        {
                            oneChangeOccured = true;
                            AddOriModification(obj, relationMember.Name, objMember, cloneMember, handle);
                        }
                    }
                }
                if (fieldBasedMergeActive)
                {
                    MergePrimitivesFieldBased(metaData, obj, clone, handle);
                    return;
                }
                bool additionalRound;
                do
                {
                    additionalRound = !oneChangeOccured;
                    foreach (PrimitiveMember primitiveMember in metaData.PrimitiveMembers)
                    {
                        if (!metaData.IsMergeRelevant(primitiveMember))
                        {
                            continue;
                        }
                        Object objValue = primitiveMember.GetValue(obj, true);
                        if (oneChangeOccured)
                        {
                            AddModification(obj, primitiveMember.Name, primitiveMember.ElementType, objValue, null, handle);
                            continue;
                        }
                        Object cloneValue = primitiveMember.GetValue(clone, true);
                        if (!ArePrimitivesEqual(metaData, primitiveMember, objValue, cloneValue, handle))
                        {
                            oneChangeOccured = true;
                            break;
                        }
                    }
                }while (additionalRound && oneChangeOccured);
            }
            finally
            {
                PrimitiveMember versionMember = metaData.VersionMember;
                if (oneChangeOccured && versionMember != null)
                {
                    // Check for early optimistic locking (Another, later level is directly on persistence layer)
                    Object versionToMerge = versionMember.GetValue(obj, true);
                    Object currentVersion = versionMember.GetValue(clone, true);

                    int compareResult = ((IComparable)versionToMerge).CompareTo(currentVersion);
                    if (ExactVersionForOptimisticLockingRequired ? compareResult != 0 : compareResult < 0)
                    {
                        throw new OptimisticLockException(currentVersion, versionToMerge, obj);
                    }
                }
            }
        }
        public virtual void DataChanged(IDataChange dataChange, DateTime dispatchTime, long sequenceId)
        {
            dataChange = dataChange.Derive(InterestedEntityTypes);
            if (dataChange.IsEmpty)
            {
                return;
            }
            ISet <Object> directObjectsToDelete = null;

            ISet <Type> requestedTypes = new HashSet <Type>();
            IDictionary <Type, IEntityMetaData> typeToMetaDataDict = new Dictionary <Type, IEntityMetaData>();

            GuiThreadHelper.InvokeInGuiAndWait(delegate()
            {
                IList <T> entities = Model.Objects;

                for (int i = entities.Count; i-- > 0;)
                {
                    Object entity = entities[i];

                    requestedTypes.Add(entity.GetType());
                }
            });

            IList <IDataChangeEntry> dataChangeEntries = dataChange.Inserts;

            for (int a = dataChangeEntries.Count; a-- > 0;)
            {
                requestedTypes.Add(dataChangeEntries[a].EntityType);
            }
            dataChangeEntries = dataChange.Updates;
            for (int a = dataChangeEntries.Count; a-- > 0;)
            {
                requestedTypes.Add(dataChangeEntries[a].EntityType);
            }
            dataChangeEntries = dataChange.Deletes;
            for (int a = dataChangeEntries.Count; a-- > 0;)
            {
                requestedTypes.Add(dataChangeEntries[a].EntityType);
            }

            IList <IEntityMetaData> metaDatas = EntityMetaDataProvider.GetMetaData(ListUtil.ToList(requestedTypes));

            foreach (IEntityMetaData metaData in metaDatas)
            {
                typeToMetaDataDict[metaData.EntityType] = metaData;
            }

            bool consistsOnlyOfDirectDeletes = false;

            if (dataChange.Deletes.Count > 0)
            {
                consistsOnlyOfDirectDeletes = true;
                foreach (IDataChangeEntry deleteEntry in dataChange.Deletes)
                {
                    if (deleteEntry is DirectDataChangeEntry)
                    {
                        if (directObjectsToDelete == null)
                        {
                            directObjectsToDelete = new IdentityHashSet <Object>();
                        }
                        directObjectsToDelete.Add(((DirectDataChangeEntry)deleteEntry).Entry);
                    }
                    else
                    {
                        consistsOnlyOfDirectDeletes = false;
                    }
                }
            }

            IList <T> interestingEntities = null;

            Object[]                contextInformation = GetContextInformation();
            IFilterDescriptor       filterDescriptor   = GetFilterDescriptor();
            IList <ISortDescriptor> sortDescriptors    = GetSortDescriptors();
            IPagingRequest          pagingRequest      = GetPagingRequest();

            IPagingResponse         pagingResponse  = null;
            List <IDataChangeEntry> modifiedEntries = new List <IDataChangeEntry>();

            modifiedEntries.AddRange(dataChange.All);

            if (!consistsOnlyOfDirectDeletes)
            {
                interestingEntities = CacheContext.ExecuteWithCache(CacheProvider.GetCurrentCache(), delegate()
                {
                    ConfigureCacheWithEagerLoads(Cache);
                    if (Refresher is IPagingRefresher <T> )
                    {
                        interestingEntities = new List <T>();
                        pagingResponse      = ((IPagingRefresher <T>)Refresher).Refresh(modifiedEntries, filterDescriptor, sortDescriptors, pagingRequest, contextInformation);
                        foreach (Object obj in pagingResponse.Result)
                        {
                            interestingEntities.Add((T)obj);
                        }
                        return(interestingEntities);
                    }
                    else
                    {
                        if (filterDescriptor != null || sortDescriptors != null)
                        {
                            contextInformation    = new Object[2];
                            contextInformation[0] = filterDescriptor;
                            contextInformation[1] = sortDescriptors;
                        }

                        return(((IRefresher <T>)Refresher).Refresh(modifiedEntries, contextInformation));
                    }
                });
            }
            GuiThreadHelper.InvokeInGuiAndWait(delegate()
            {
                IList <T> entities = Model.Objects;

                ISet <T> entitiesToAdd                           = null;
                ISet <T> entitiesToRemove                        = null;
                IDictionary <T, T> entitiesToReplace             = null;
                IDictionary <IObjRef, T> oldObjRefToOldEntityMap = null;
                bool mergeModel = false;

                if (interestingEntities != null && interestingEntities.Count > 0)
                {
                    entitiesToAdd           = new IdentityHashSet <T>(interestingEntities);
                    entitiesToRemove        = new IdentityHashSet <T>(entities);
                    entitiesToReplace       = new IdentityDictionary <T, T>();
                    oldObjRefToOldEntityMap = new Dictionary <IObjRef, T>();
                    mergeModel = true;
                }
                for (int i = entities.Count; i-- > 0;)
                {
                    T oldEntity = entities[i];
                    if (directObjectsToDelete != null && directObjectsToDelete.Contains(oldEntity))
                    {
                        if (entitiesToRemove != null)
                        {
                            entitiesToRemove.Remove(oldEntity);
                        }
                        Model.RemoveAt(i);
                        continue;
                    }
                    Type oldEntityType       = ProxyHelper.GetRealType(oldEntity.GetType());
                    PrimitiveMember idMember = typeToMetaDataDict[oldEntityType].IdMember;
                    Object oldEntityId       = idMember.GetValue(oldEntity, false);
                    if (oldEntityId == null)
                    {
                        if (entitiesToRemove != null)
                        {
                            entitiesToRemove.Remove(oldEntity);
                        }
                        // Unpersisted object. This object should not be removed
                        // only because of a background DCE
                        continue;
                    }
                    bool entryRemoved = false;
                    foreach (IDataChangeEntry deleteEntry in dataChange.Deletes)
                    {
                        if (deleteEntry is DirectDataChangeEntry)
                        {
                            continue;
                        }
                        Object id = deleteEntry.Id;
                        if (!EqualsItems(oldEntityType, oldEntityId, deleteEntry.EntityType, id))
                        {
                            continue;
                        }
                        if (entitiesToRemove != null)
                        {
                            entitiesToRemove.Remove(oldEntity);
                        }
                        Model.RemoveAt(i);
                        entryRemoved = true;
                        break;
                    }
                    if (entryRemoved)
                    {
                        continue;
                    }
                    if (mergeModel)
                    {
                        IObjRef oldObjRef   = new ObjRef(oldEntityType, ObjRef.PRIMARY_KEY_INDEX, oldEntityId, null);
                        T existingOldEntity = DictionaryExtension.ValueOrDefault(oldObjRefToOldEntityMap, oldObjRef);
                        if (existingOldEntity == null)
                        {
                            oldObjRefToOldEntityMap.Add(oldObjRef, oldEntity);
                        }
                        else if (!Object.ReferenceEquals(existingOldEntity, oldEntity))
                        {
                            // Force duplicate key exception
                            oldObjRefToOldEntityMap.Add(oldObjRef, oldEntity);
                        }
                    }
                }
                if (oldObjRefToOldEntityMap != null && oldObjRefToOldEntityMap.Count > 0)
                {
                    IDictionary <IObjRef, T> newObjRefToNewEntityMap = new Dictionary <IObjRef, T>();
                    for (int a = interestingEntities.Count; a-- > 0;)
                    {
                        T newEntity              = interestingEntities[a];
                        Type newEntityType       = ProxyHelper.GetRealType(newEntity.GetType());
                        PrimitiveMember idMember = typeToMetaDataDict[newEntityType].IdMember;
                        Object newEntityId       = idMember.GetValue(newEntity, false);

                        IObjRef newObjRef = new ObjRef(newEntityType, ObjRef.PRIMARY_KEY_INDEX, newEntityId, null);
                        newObjRefToNewEntityMap.Add(newObjRef, newEntity);
                    }
                    DictionaryExtension.Loop(oldObjRefToOldEntityMap, delegate(IObjRef objRef, T oldEntity)
                    {
                        T newEntity = DictionaryExtension.ValueOrDefault(newObjRefToNewEntityMap, objRef);
                        if (newEntity == null)
                        {
                            // Nothing to do if current oldEntity has no corresponding newEntity
                            return;
                        }
                        entitiesToAdd.Remove(newEntity);
                        if (!Object.ReferenceEquals(oldEntity, newEntity) &&
                            (dataChange.IsLocalSource || !(oldEntity is IDataObject) || !((IDataObject)oldEntity).ToBeUpdated))
                        {
                            entitiesToReplace[oldEntity] = newEntity;
                        }
                        entitiesToRemove.Remove(oldEntity);
                    });
                }

                if (mergeModel)
                {
                    for (int a = entities.Count; a-- > 0;)
                    {
                        T item = entities[a];
                        if (entitiesToRemove.Contains(item))
                        {
                            Model.RemoveAt(a);
                            continue;
                        }
                        T replacingItem = DictionaryExtension.ValueOrDefault(entitiesToReplace, item);
                        if (replacingItem != null)
                        {
                            Model.Replace(a, replacingItem);
                            continue;
                        }
                    }
                    IEnumerator <T> enumerator = entitiesToAdd.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        T entityToAdd = enumerator.Current;
                        Model.Add(entityToAdd);
                    }

                    if (hasPagedViewModel)
                    {
                        UpdatePagingInformation(pagingResponse);
                    }
                    UpdateAfterDCE();
                }
            });
        }
Esempio n. 3
0
        protected void ApplyChangesToOriginalsIntern(ICUDResult cudResult, IOriCollection oriCollection, ICache cache)
        {
            ICacheModification      cacheModification      = this.CacheModification;
            IConversionHelper       conversionHelper       = this.ConversionHelper;
            IEntityMetaDataProvider entityMetaDataProvider = this.EntityMetaDataProvider;
            IList <Object>          originalRefs           = cudResult.GetOriginalRefs();
            IList <IObjRef>         allChangeORIs          = oriCollection.AllChangeORIs;

            String[] allChangedBy    = oriCollection.AllChangedBy;
            long[]   allChangedOn    = oriCollection.AllChangedOn;
            String   singleChangedBy = oriCollection.ChangedBy;
            long?    singleChangedOn = oriCollection.ChangedOn;

            bool           newInstanceOnCall         = CacheProvider.IsNewInstanceOnCall;
            IList <Object> validObjects              = new List <Object>(originalRefs.Count);
            bool           oldCacheModificationValue = CacheModification.Active;

            CacheModification.Active = true;
            try
            {
                for (int a = originalRefs.Count; a-- > 0;)
                {
                    Object  originalRef = originalRefs[a];
                    IObjRef ori         = allChangeORIs[a];

                    if (originalRef == null)
                    {
                        // Object has been deleted by cascade delete contraints on server merge or simply a "not specified" original ref
                        continue;
                    }
                    if (originalRef is IObjRef)
                    {
                        continue;
                    }
                    long?           changedOn     = allChangedOn != null ? allChangedOn[a] : singleChangedOn;
                    String          changedBy     = allChangedBy != null ? allChangedBy[a] : singleChangedBy;
                    IEntityMetaData metaData      = ((IEntityMetaDataHolder)originalRef).Get__EntityMetaData();
                    PrimitiveMember versionMember = metaData.VersionMember;

                    PrimitiveMember keyMember = metaData.IdMember;

                    PrimitiveMember onMember, byMember;
                    if (keyMember.GetValue(originalRef, false) == null)
                    {
                        onMember = metaData.CreatedOnMember;
                        byMember = metaData.CreatedByMember;
                    }
                    else
                    {
                        onMember = metaData.UpdatedOnMember;
                        byMember = metaData.UpdatedByMember;
                    }
                    if (onMember != null && changedOn != null)
                    {
                        Object createdOn = ConversionHelper.ConvertValueToType(onMember.ElementType, changedOn);
                        onMember.SetValue(originalRef, createdOn);
                    }
                    if (byMember != null && changedBy != null)
                    {
                        Object createdBy = ConversionHelper.ConvertValueToType(byMember.ElementType, changedBy);
                        byMember.SetValue(originalRef, createdBy);
                    }
                    if (ori == null)
                    {
                        keyMember.SetValue(originalRef, null);
                        if (versionMember != null)
                        {
                            versionMember.SetValue(originalRef, null);
                        }
                        if (originalRef is IDataObject)
                        {
                            ((IDataObject)originalRef).ToBeUpdated = false;
                            ((IDataObject)originalRef).ToBeDeleted = false;
                        }
                        continue; // Object has been deleted directly
                    }
                    keyMember.SetValue(originalRef, ConversionHelper.ConvertValueToType(keyMember.RealType, ori.Id));
                    if (versionMember != null)
                    {
                        if (AlwaysUpdateVersionInChangedEntities)
                        {
                            versionMember.SetValue(originalRef, ConversionHelper.ConvertValueToType(versionMember.RealType, ori.Version));
                        }
                        else
                        {
                            // We INTENTIONALLY do NOT set the version and let it on its old value, to force the following DCE to refresh the cached object with 'real' data
                            // If we set the version here to the ori.getVersion(), the DCE will 'see' a already valid object - but is IS NOT valid
                            // because it may not contain bi-directional information which can only be resolved by reloading the object from persistence layer
                            //versionMember.SetValue(originalRef, null);
                        }
                    }
                    if (originalRef is IDataObject)
                    {
                        ((IDataObject)originalRef).ToBeUpdated = false;
                        ((IDataObject)originalRef).ToBeDeleted = false;
                    }
                    validObjects.Add(originalRef);
                }
                PutInstancesToCurrentCache(validObjects, cache);
            }
            finally
            {
                CacheModification.Active = oldCacheModificationValue;
            }
        }
Esempio n. 4
0
        public ICollection <T> ExtractTargetEntities <T, S>(IEnumerable <S> sourceEntities, String sourceToTargetEntityPropertyPath)
        {
            // Einen Accessor ermitteln, der die gesamte Hierachie aus dem propertyPath („A.B.C“) selbstständig traversiert
            Member member = MemberTypeProvider.GetMember(typeof(S), sourceToTargetEntityPropertyPath);

            // MetaDaten der Ziel-Entity ermitteln, da wir (generisch) den PK brauchen, um damit ein DISTINCT-Behavior durch eine Map als Zwischenstruktur zu
            // erreichen
            IEntityMetaData targetMetaData = EntityMetaDataProvider.GetMetaData(member.ElementType);
            PrimitiveMember targetIdMember = targetMetaData.IdMember;

            // Damit bei der Traversion keine Initialisierungen mit DB-Roundtrips entstehen, machen wir vorher eine Prefetch passend zum PropertyPath auf allen
            // übergebenen Quell-Entities
            // Dadurch entstehen maximal 2 gebatchte SELECTs, egal wie groß die Liste ist
            IPrefetchHandle prefetch = CreatePrefetch().Add(typeof(S), sourceToTargetEntityPropertyPath).Build();
            // Speichere das State-Result unbenutzt - wichtig für concurrent GC Aktivitäten, um Verluste an Entity-Referenzen zu verhindern
            IPrefetchState state = prefetch.Prefetch(sourceEntities);

            IDictionary <Object, T> targetDistinctMap = new Dictionary <Object, T>();

            // Danach traversieren, wobei wir jetzt wissen, dass uns das keine Roundtrips kostet
            foreach (S sourceEntity in sourceEntities)
            {
                if (sourceEntity == null)
                {
                    continue;
                }
                Object targetEntities = member.GetValue(sourceEntity);
                if (targetEntities == null)
                {
                    continue;
                }
                // Ergebnismenge flexibel (bei *-To-Many) verarbeiten oder so lassen (bei *-To-One)
                if (targetEntities is IEnumerable)
                {
                    foreach (Object targetEntity in (IEnumerable)targetEntities)
                    {
                        if (targetEntity == null)
                        {
                            continue;
                        }
                        Object targetId = targetIdMember.GetValue(targetEntity);
                        if (targetId == null)
                        {
                            // Falls die Entity keine ID hat, speichern wir sie ausnahmsweise selbst als Key
                            targetId = targetEntity;
                        }
                        targetDistinctMap[targetId] = (T)targetEntity;
                    }
                }
                else
                {
                    Object targetId = targetIdMember.GetValue(targetEntities);
                    if (targetId == null)
                    {
                        // Falls die Entity keine ID hat, speichern wir sie ausnahmsweise selbst als Key
                        targetId = targetEntities;
                    }
                    targetDistinctMap[targetId] = (T)targetEntities;
                }
            }
            // Alle values sind unsere eindeutigen Target Entities ohne Duplikate
            return(targetDistinctMap.Values);
        }