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 void AfterStarted() { directObjRefDirectMember = MemberTypeProvider.GetMember(typeof(DirectObjRef), "Direct"); }
public override IClassVisitor Extend(IClassVisitor visitor, IBytecodeBehaviorState state, IList <IBytecodeBehavior> remainingPendingBehaviors, IList <IBytecodeBehavior> cascadePendingBehaviors) { MemberEnhancementHint memberHint = state.GetContext <MemberEnhancementHint>(); if (memberHint == null) { return(visitor); } RelationMemberEnhancementHint relationMemberHint = state.GetContext <RelationMemberEnhancementHint>(); String[] memberNameSplit = EmbeddedMember.Split(memberHint.MemberName); if (memberNameSplit.Length == 1) { IPropertyInfo[] sPropertyPath = new IPropertyInfo[1]; sPropertyPath[0] = PropertyInfoProvider.GetProperty(memberHint.DeclaringType, memberHint.MemberName); visitor = new EntityMetaDataMemberVisitor(visitor, memberHint.DeclaringType, memberHint.DeclaringType, memberHint.MemberName, EntityMetaDataProvider, sPropertyPath); if (relationMemberHint != null) { visitor = new EntityMetaDataRelationMemberVisitor(visitor, memberHint.DeclaringType, memberHint.MemberName, sPropertyPath); } else { visitor = new EntityMetaDataPrimitiveMemberVisitor(visitor, memberHint.DeclaringType, memberHint.MemberName, sPropertyPath); } return(visitor); } Member[] members = new Member[memberNameSplit.Length]; Type currType = memberHint.DeclaringType; IPropertyInfo[] propertyPath = new IPropertyInfo[members.Length]; StringBuilder sb = new StringBuilder(); for (int a = 0, size = memberNameSplit.Length; a < size; a++) { if (a + 1 < memberNameSplit.Length) { members[a] = MemberTypeProvider.GetMember(currType, memberNameSplit[a]); } else if (relationMemberHint != null) { members[a] = MemberTypeProvider.GetRelationMember(currType, memberNameSplit[a]); } else { members[a] = MemberTypeProvider.GetPrimitiveMember(currType, memberNameSplit[a]); } if (a > 0) { sb.Append('.'); } sb.Append(members[a].Name); propertyPath[a] = PropertyInfoProvider.GetProperty(currType, memberNameSplit[a]); if (a + 1 < memberNameSplit.Length) { currType = BytecodeEnhancer.GetEnhancedType(members[a].RealType, new EmbeddedEnhancementHint(memberHint.DeclaringType, currType, sb.ToString())); } else { currType = members[a].RealType; } } visitor = new EntityMetaDataMemberVisitor(visitor, memberHint.DeclaringType, memberHint.DeclaringType, memberHint.MemberName, EntityMetaDataProvider, propertyPath); if (relationMemberHint != null) { visitor = new EntityMetaDataRelationMemberVisitor(visitor, memberHint.DeclaringType, memberHint.MemberName, propertyPath); } else { visitor = new EntityMetaDataPrimitiveMemberVisitor(visitor, memberHint.DeclaringType, memberHint.MemberName, propertyPath); } visitor = new EntityMetaDataEmbeddedMemberVisitor(visitor, memberHint.DeclaringType, memberHint.MemberName, members); return(visitor); }