public static string GetConcurrencyToken <TEntity>(this IEntityPropertyAccessor entityPropertyAccessor, TEntity entityType, object entity) { if (entityPropertyAccessor == null) { throw new ArgumentNullException(nameof(entityPropertyAccessor)); } return(entityPropertyAccessor.GetConcurrencyToken(typeof(TEntity), entity)); }
public ProductDeleteModel ProjectToDeleteModel(Product product, [Inject] IEntityPropertyAccessor propertyManager) { if (product == null) { return(null); } var concurrencyToken = propertyManager.GetConcurrencyToken(typeof(Product), product); return(new ProductDeleteModel { Id = product.Id, ConcurrencyToken = concurrencyToken }); }
public override async ValueTask <IDispatchResult> ProcessAsync <TMessage>(DispatchDataDictionary <TMessage> dispatchData, Func <DispatchDataDictionary <TMessage>, ValueTask <IDispatchResult> > next, CancellationToken cancellation) { var message = dispatchData.Message; var handler = Context.MessageHandler; var descriptor = EntityMessageHandlerContextDescriptor.GetDescriptor(handler.GetType()); if (!descriptor.IsEntityMessageHandler) { return(await next(dispatchData)); } if (!TryGetEntityLookup(message, descriptor, out var entityLookup)) { return(await next(dispatchData)); } var messageAccessor = GetMessageAccessor(); var checkConcurrencyToken = messageAccessor.TryGetConcurrencyToken(message, out var concurrencyToken); do { var entity = await entityLookup(cancellation); var createsEntityAttribute = Context.MessageHandlerAction.Member.GetCustomAttribute <CreatesEntityAttribute>(); if (entity == null) { if (createsEntityAttribute == null || !createsEntityAttribute.CreatesEntity) { return(new EntityNotFoundDispatchResult(descriptor.EntityType)); } } else { if (createsEntityAttribute != null && createsEntityAttribute.CreatesEntity && !createsEntityAttribute.AllowExisingEntity) { if (!_entityPropertyAccessor.TryGetId(descriptor.EntityType, entity, out var id)) { return(new EntityAlreadyPresentDispatchResult(descriptor.EntityType)); } else { return(new EntityAlreadyPresentDispatchResult(descriptor.EntityType, id)); } } if (checkConcurrencyToken && concurrencyToken != _entityPropertyAccessor.GetConcurrencyToken(descriptor.EntityType, entity)) { return(new ConcurrencyIssueDispatchResult()); } descriptor.SetHandlerEntity(handler, entity); } var originalEntity = entity; var dispatchResult = await next(dispatchData); if (!dispatchResult.IsSuccess) { return(dispatchResult); } var markedAsDeleted = descriptor.IsMarkedAsDeleted(handler); entity = descriptor.GetHandlerEntity(handler); try { // The Store/Delete calls must be protected to be called with a null entity. if (entity != null || originalEntity != null) // TODO: Do we care about events etc. here? { if (!_entityPropertyAccessor.TryGetId(descriptor.EntityType, entity ?? originalEntity, out var id)) { return(new FailureDispatchResult("Unable to determine the id of the specified entity.")); } if (markedAsDeleted || entity == null) { await _entityStorageEngine.DeleteAsync(descriptor.EntityType, entity ?? originalEntity, id); } else if (await _entityStorageEngine.TryStoreAsync(descriptor.EntityType, entity, id)) { dispatchResult = AddAdditionalResultData(descriptor, entity, dispatchResult); } else { continue; } } } catch (ConcurrencyException) { Assert(false); continue; } catch (StorageException exc) { return(new StorageIssueDispatchResult(exc)); } catch (Exception exc) { return(new FailureDispatchResult(exc)); } return(dispatchResult); }while (!checkConcurrencyToken); return(new ConcurrencyIssueDispatchResult()); }