public IPrefetchHandle Union(IPrefetchHandle otherPrefetchHandle) { if (otherPrefetchHandle == null) { return(this); } LinkedHashMap <Type, CHashSet <AppendableCachePath> > newMap = LinkedHashMap <Type, CHashSet <AppendableCachePath> > .Create(entityTypeToPrefetchSteps.Count); foreach (Entry <Type, PrefetchPath[]> entry in entityTypeToPrefetchSteps) { CHashSet <AppendableCachePath> prefetchPaths = newMap.Get(entry.Key); if (prefetchPaths == null) { prefetchPaths = new CHashSet <AppendableCachePath>(); newMap.Put(entry.Key, prefetchPaths); } foreach (PrefetchPath cachePath in entry.Value) { prefetchPaths.Add(cachePathHelper.CopyCachePathToAppendable(cachePath)); } } foreach (Entry <Type, PrefetchPath[]> entry in ((PrefetchHandle)otherPrefetchHandle).entityTypeToPrefetchSteps) { CHashSet <AppendableCachePath> prefetchPaths = newMap.Get(entry.Key); if (prefetchPaths == null) { prefetchPaths = new CHashSet <AppendableCachePath>(); newMap.Put(entry.Key, prefetchPaths); } foreach (PrefetchPath cachePath in entry.Value) { AppendableCachePath clonedCachePath = cachePathHelper.CopyCachePathToAppendable(cachePath); if (prefetchPaths.Add(clonedCachePath)) { continue; } AppendableCachePath existingCachePath = prefetchPaths.Get(clonedCachePath); cachePathHelper.UnionCachePath(existingCachePath, clonedCachePath); } } LinkedHashMap <Type, PrefetchPath[]> targetMap = LinkedHashMap <Type, PrefetchPath[]> .Create(newMap.Count); foreach (Entry <Type, CHashSet <AppendableCachePath> > entry in newMap) { PrefetchPath[] cachePaths = cachePathHelper.CopyAppendableToCachePath(entry.Value); targetMap.Put(entry.Key, cachePaths); } return(new PrefetchHandle(targetMap, cachePathHelper)); }
public void Test_Prefetch() { Object obj = new UsableObservableCollection <Object>(); IList <TestEntity> testEntities = HelloWorldService.GetAllTestEntities(); Assert.AssertNotEquals(0, testEntities.Count); IPrefetchHandle prefetch = PrefetchHelper.CreatePrefetch().Add(typeof(TestEntity), "Relation").Add(typeof(TestEntity), "Relations").Build(); prefetch.Prefetch(testEntities); IEntityMetaData metaData = EntityMetaDataProvider.GetMetaData(typeof(TestEntity)); int indexOfRelation = metaData.GetIndexByRelationName("Relation"); int indexOfRelations = metaData.GetIndexByRelationName("Relations"); foreach (TestEntity testEntity in testEntities) { Assert.AssertTrue(((IObjRefContainer)testEntity).Is__Initialized(indexOfRelation)); Assert.AssertTrue(((IObjRefContainer)testEntity).Is__Initialized(indexOfRelations)); } }
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); }
public virtual void AfterStarted() { prefetch = PrefetchHelper.CreatePrefetch().Add(typeof(TestEntity), "Relations").Build(); }