public Object ProcessServiceResult(Object result, IList <IObjRef> objRefs, IList <Object> entities, Type expectedType, Object[] serviceRequestArgs, Attribute annotation) { IPagingResponse pagingResponse = (IPagingResponse)result; QueryResultType queryResultType = QueryResultType.REFERENCES; if (annotation is FindAttribute) { queryResultType = ((FindAttribute)annotation).ResultType; } switch (queryResultType) { case QueryResultType.BOTH: pagingResponse.RefResult = objRefs; pagingResponse.Result = entities; break; case QueryResultType.ENTITIES: pagingResponse.RefResult = null; pagingResponse.Result = entities; break; case QueryResultType.REFERENCES: pagingResponse.RefResult = objRefs; pagingResponse.Result = null; break; default: throw RuntimeExceptionUtil.CreateEnumNotSupportedException(queryResultType); } return(pagingResponse); }
// After each Find, the paging properties of the viewmodel must be updated: public virtual void UpdatePagingInformation(IPagingResponse pagingResponse) { if (pagingResponse != null) { Model.ItemCount = pagingResponse.TotalSize; Model.PageIndex = pagingResponse.Number; } }
public virtual IList <T> GetObjectsFromPagingResponse(IPagingResponse pagingResponse) { IList <T> result = new List <T>(); foreach (Object obj in pagingResponse.Result) { result.Add((T)obj); } return(result); }
protected virtual void PopulateAsync(GenericViewModel <T> model, IFilterDescriptor filterDescriptor, IList <ISortDescriptor> sortDescriptors, IPagingRequest pagingRequest, Object[] contextInformation, ICache cache, Object localRequest) { lock (currentRequestLock) { // Early check here, but more important check in the finally-SyncContext. // We will not update the ViewModel, if this request is not the current request (hence Populate was recalled // since this request was initiated). // An example where this is important would be a screen, where the user can enter search criteria and start // a corresponding search, while the screen is still loading data from a preceeding request. In this case, the // result of the second search could be retrieved before the first one, leading to wrong data in the screen. // // ToDo: Is there a scenario where the same VMDCC is used with multiple VMs or different Caches? // If so, localRequest and currentRequest must contain the VM and Cache references to compare them! if (!Object.ReferenceEquals(localRequest, currentRequest)) { return; } } IList <T> initialEntities = null; IPagingResponse pagingResponse = null; try { if (hasPagedViewModel) { pagingResponse = ((IPagingRefresher <T>)Refresher).Populate(filterDescriptor, sortDescriptors, pagingRequest, contextInformation); initialEntities = new List <T>(); foreach (Object obj in pagingResponse.Result) { initialEntities.Add((T)obj); } } else { if (filterDescriptor != null || sortDescriptors != null) { contextInformation = new Object[2]; contextInformation[0] = filterDescriptor; contextInformation[1] = sortDescriptors; } initialEntities = ((IRefresher <T>)Refresher).Populate(contextInformation); } } catch (Exception e) { if (Log.ErrorEnabled) { Log.Error(e); } } finally { GuiThreadHelper.InvokeInGui(delegate() { lock (currentRequestLock) { if (!Object.ReferenceEquals(localRequest, currentRequest)) { return; } } try { if (IsRefreshedDataValid(contextInformation)) { if (initialEntities != null) { if (ToBeCreatedOnTop) { // ToBeCreated entities are never part of the initialEntities, so no doublette check necessary foreach (T entity in model.Objects) { if ((entity is IDataObject) && ((IDataObject)entity).ToBeCreated) { initialEntities.Insert(0, entity); } } } model.Clear(); for (int a = 0, size = initialEntities.Count; a < size; a++) { T item = initialEntities[a]; model.InsertAt(a, item); } } // Important to update the sorting states (if the provider disables gridviews own sorting mechanism): if (hasPagedViewModel) { UpdatePagingInformation(pagingResponse); } UpdateAfterDCE(); } } catch (Exception ex) { if (Log.ErrorEnabled) { Log.Error(ex); } } finally { model.IsBusy = false; } }); } }
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(); } }); }