private void LoadRelatedPostProcess <T>( IEnumerable <T> sourceEntities, LoadRelatedOptions options, LoadRelatedPreProcessInfo preProcessInfo) { JToken[] rows = ClientAdaper.GetDocuments(preProcessInfo.EntityIdsToLoad); EntitiesProcessResult processResult = Process(rows, new OdmViewProcessingOptions()); Dictionary <string, EntitiesProcessResult> viewsSelectResult = SelectToManyFromViews(preProcessInfo); foreach (T sourceEntity in sourceEntities) { string entityId = GetEntityInstanceId(sourceEntity); JToken document = DocumentManager.DocInfo(entityId).Document; // ToOne foreach (PropertyInfo toOneProp in options.ToOne) { string relatedEntityId = GetRelatedToOneEntityId(document, toOneProp); object relatedToOneEntity = processResult.GetEntity(relatedEntityId); // This line was comment out because it is possible to get null related entity // when the property is optional. This check needs to be done only for required properties. //if (relatedToOneEntity == null) throw new Exception("Fail to find ToOne related entity for property " + toOneProp); toOneProp.SetValue(sourceEntity, relatedToOneEntity); } // ToOne already loaded foreach (PropertyInfo toOneProp in options.ToOneExist) { string relatedEntityId = GetRelatedToOneEntityId(document, toOneProp); object relatedToOneEntity = identityMap.GetEntityById(relatedEntityId); if (relatedToOneEntity == null) { throw new Exception("Fail to find ToOneExist related entity for property " + toOneProp); } toOneProp.SetValue(sourceEntity, relatedToOneEntity); } // ToMany Direct foreach (PropertyInfo toManyDirectProp in options.ToManyDirect) { string[] relatedEntitiesIds = GetRelatedToManyEntitiesIds(document, toManyDirectProp); if (relatedEntitiesIds != null) { serializer.SetDirectAssoicationCollectionProperty(sourceEntity, toManyDirectProp, relatedEntitiesIds); } } // ToMany Inverse foreach (LoadRelatedWithViewInfo toManyViewInfo in options.ToManyView) { EntitiesProcessResult viewProcessResult = viewsSelectResult[toManyViewInfo.ViewName]; string[] relatedEntitiesIds = viewProcessResult.GetRelatedEntitiesIds(entityId); AssociationAttribute associationAttr = AssociationAttribute.GetSingle(toManyViewInfo.PropertyInfo); serializer.SetInverseAssociationCollectionInternal( sourceEntity, toManyViewInfo.PropertyInfo, associationAttr, relatedEntitiesIds); } } }
/// <summary> /// Load specified related entities of the sourceEntities. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="sourceEntities"></param> /// <param name="configOptions"></param> public void LoadRelated <T>(IEnumerable <T> sourceEntities, Action <LoadRelatedOptionsBuilder <T> > configOptions) { var optionsBuilder = new LoadRelatedOptionsBuilder <T>(); configOptions(optionsBuilder); LoadRelatedOptions options = optionsBuilder.Build(); // First pre-process all the source entities and find the relatd entities to load. LoadRelatedPreProcessInfo preProcessInfo = LoadRelatedPreProcess(sourceEntities, options); // Load the related entities and set the association properties. LoadRelatedPostProcess(sourceEntities, options, preProcessInfo); }
private LoadRelatedPreProcessInfo LoadRelatedPreProcess <T>(IEnumerable <T> sourceEntities, LoadRelatedOptions options) { var builder = new LoadRelatedPreProcessInfoBuilder(); foreach (T sourceEntity in sourceEntities) { string entityId = GetEntityInstanceId(sourceEntity); JToken document = DocumentManager.DocInfo(entityId).Document; Debug.Assert(document != null, "Fail to find the original document of the entity " + sourceEntity); // Find all ToOne associations to load foreach (PropertyInfo toOneProp in options.ToOne) { string relatedEntityId = GetRelatedToOneEntityId(document, toOneProp); if (!string.IsNullOrEmpty(relatedEntityId)) { builder.RelatedEntityIdsToLoad.Add(relatedEntityId); } } // Find all ToMany associations to load foreach (PropertyInfo toManyDirectProp in options.ToManyDirect) { string[] relatedEntitiesIds = GetRelatedToManyEntitiesIds(document, toManyDirectProp) ?? new string[0]; foreach (string relatedEntityId in relatedEntitiesIds) { builder.RelatedEntityIdsToLoad.Add(relatedEntityId); } } // Prepare all Inverse-ToMany with views. foreach (LoadRelatedWithViewInfo inverseToMany in options.ToManyView) { builder.AddViewSelection(inverseToMany.ViewName, GetEntityInstanceId(sourceEntity)); } } return(builder.Build()); }