Пример #1
0
        public static List <QueryEntity> CherryPickSelectedProperties <TQueryableEntity>(
            this IEnumerable <QueryEntity> entities,
            QueryClause <TQueryableEntity> query, RepositoryEntityMetadata metadata,
            IEnumerable <string> includeAdditionalProperties = null)
            where TQueryableEntity : IQueryableEntity
        {
            var selectedPropertyNames = query.GetAllSelectedFields();

            if (!selectedPropertyNames.Any())
            {
                return(entities.ToList());
            }

            selectedPropertyNames = selectedPropertyNames
                                    .Concat(new[] { nameof(QueryEntity.Id) })
                                    .Concat(includeAdditionalProperties ?? Enumerable.Empty <string>())
                                    .ToList();

            return(entities
                   .Select(resultEntity => resultEntity.Properties
                           .Where(resultEntityProperty => selectedPropertyNames.Contains(resultEntityProperty.Key)))
                   .Select(selectedProperties =>
                           EntityFromContainerProperties(selectedProperties.ToObjectDictionary(), metadata))
                   .ToList());
        }
Пример #2
0
        public static CommandEntity FromProperties(IReadOnlyDictionary <string, object> properties,
                                                   RepositoryEntityMetadata metadata)
        {
            properties.GuardAgainstNull(nameof(properties));
            metadata.GuardAgainstNull(nameof(metadata));

            if (!properties.ContainsKey(nameof(Id)) ||
                properties[nameof(Id)] == null)
            {
                throw new InvalidOperationException(
                          "Unable to create a new CommandEntity. There is no 'Id' property in this collection of values.");
            }

            var result = new CommandEntity(properties[nameof(Id)].ToString());

            foreach (var property in properties)
            {
                var propertyType = metadata.GetPropertyType(property.Key, false);
                if (propertyType != null)
                {
                    result.Add(property.Key, property.Value, propertyType);
                }
            }

            return(result);
        }
Пример #3
0
 protected RepositoryEntity(string id)
 {
     Metadata = new RepositoryEntityMetadata();
     Add(nameof(Id), id, typeof(string));
     Add(nameof(LastPersistedAtUtc), null, typeof(DateTime?));
     Add(nameof(IsDeleted), null, typeof(bool?));
 }
Пример #4
0
        public void Delete(Identifier id, bool destroy = true)
        {
            id.GuardAgainstNull(nameof(id));

            var entity = this.repository.Retrieve(this.containerName, id,
                                                  RepositoryEntityMetadata.FromType <TEntity>());

            if (entity == null)
            {
                return;
            }

            if (destroy)
            {
                this.repository.Remove(this.containerName, id);
                this.recorder.TraceDebug("Entity {Id} was destroyed in repository", id);
                return;
            }

            if (entity.IsDeleted.GetValueOrDefault(false))
            {
                return;
            }

            entity.IsDeleted = true;
            this.repository.Replace(this.containerName, id, entity);
            this.recorder.TraceDebug("Entity {Id} was soft-deleted in repository", id);
        }
Пример #5
0
        public static CommandEntity FromCommandEntity(IReadOnlyDictionary <string, object> properties,
                                                      RepositoryEntityMetadata metadata)
        {
            properties.GuardAgainstNull(nameof(properties));
            metadata.GuardAgainstNull(nameof(metadata));

            return(FromProperties(properties, metadata));
        }
Пример #6
0
        public TEntity ResurrectDeleted(Identifier id)
        {
            var entity = this.repository.Retrieve(this.containerName, id,
                                                  RepositoryEntityMetadata.FromType <TEntity>());

            if (entity == null)
            {
                return(default);
Пример #7
0
        private static QueryEntity FromProperties <TType>(IReadOnlyDictionary <string, object> properties)
            where TType : IQueryableEntity
        {
            properties.GuardAgainstNull(nameof(properties));

            var metadata = RepositoryEntityMetadata.FromType <TType>();

            return(FromProperties(properties, metadata));
        }
Пример #8
0
        public TDtoWithId Get <TDtoWithId>(Identifier id, bool includeDeleted = false)
            where TDtoWithId : IQueryableEntity, IHasIdentity, new()
        {
            id.GuardAgainstNull(nameof(id));

            var entity = this.repository.Retrieve(this.containerName, id, RepositoryEntityMetadata.FromType <TDto>());

            if (entity == null)
            {
                return(default);
Пример #9
0
        public TDtoWithId Get <TDtoWithId>(Identifier id) where TDtoWithId : IQueryableEntity, IHasIdentity, new()
        {
            id.GuardAgainstNull(nameof(id));

            var entity = this.repository.Retrieve(this.containerName, id, RepositoryEntityMetadata.FromType <TDto>());

            this.logger.LogDebug($"Entity {id} was retrieved from repository");

            return(entity == null
                ? default
                : entity.ToQueryDto <TDtoWithId>());
        }
        public TEntity Get(Identifier id)
        {
            id.GuardAgainstNull(nameof(id));

            var entity = this.repository.Retrieve(this.containerName, id,
                                                  RepositoryEntityMetadata.FromType <TEntity>());

            this.logger.LogDebug("Entity {Id} was retrieved from repository", id);

            return(entity != null
                ? entity.ToDomainEntity <TEntity>(this.domainFactory)
                : default);
Пример #11
0
        public CommandEntity Retrieve(string containerName, string id, RepositoryEntityMetadata metadata)
        {
            containerName.GuardAgainstNullOrEmpty(nameof(containerName));
            id.GuardAgainstNullOrEmpty(nameof(id));
            metadata.GuardAgainstNull(nameof(metadata));

            var container = EnsureContainer(containerName);

            if (container.Exists(id))
            {
                return(CommandEntity.FromCommandEntity(
                           container.Get(id).FromFileProperties(metadata), metadata));
            }

            return(default);
        public CommandEntity Retrieve(string containerName, string id, RepositoryEntityMetadata metadata)
        {
            containerName.GuardAgainstNullOrEmpty(nameof(containerName));
            id.GuardAgainstNullOrEmpty(nameof(id));
            metadata.GuardAgainstNull(nameof(metadata));

            if (this.containers.ContainsKey(containerName))
            {
                if (this.containers[containerName].ContainsKey(id))
                {
                    return(CommandEntity.FromCommandEntity(
                               this.containers[containerName][id].FromDictionaryProperties(), metadata));
                }
            }

            return(default);
Пример #13
0
        public QueryResults <TDto> Query(QueryClause <TDto> query)
        {
            if (query == null || query.Options.IsEmpty)
            {
                this.logger.LogDebug("No entities were retrieved from repository, the query is empty");

                return(new QueryResults <TDto>(new List <TDto>()));
            }

            var entities = this.repository.Query(this.containerName, query,
                                                 RepositoryEntityMetadata.FromType <TDto>());

            this.logger.LogDebug($"{entities.Count} Entities were retrieved from repository");

            return(new QueryResults <TDto>(entities.ConvertAll(x => x.ToEntity <TDto>(this.domainFactory))));
        }
Пример #14
0
        public QueryResults <TDto> Query(QueryClause <TDto> query, bool includeDeleted = false)
        {
            if (query == null || query.Options.IsEmpty)
            {
                this.recorder.TraceDebug("No entities were retrieved from repository, the query is empty");

                return(new QueryResults <TDto>(new List <TDto>()));
            }

            var entities = this.repository.Query(this.containerName, query,
                                                 RepositoryEntityMetadata.FromType <TDto>());

            entities = entities
                       .Where(e => !e.IsDeleted.GetValueOrDefault(false) || includeDeleted)
                       .ToList();

            this.recorder.TraceDebug($"{entities.Count} Entities were retrieved from repository");
            return(new QueryResults <TDto>(entities.ConvertAll(x => x.ToEntity <TDto>(this.domainFactory))));
        }
Пример #15
0
        public static QueryEntity FromProperties(IReadOnlyDictionary <string, object> properties,
                                                 RepositoryEntityMetadata metadata)
        {
            properties.GuardAgainstNull(nameof(properties));
            metadata.GuardAgainstNull(nameof(metadata));

            var dataEntity = new QueryEntity();

            foreach (var pair in properties)
            {
                var propertyType = metadata.GetPropertyType(pair.Key, false);
                if (propertyType != null)
                {
                    dataEntity.Add(pair.Key, pair.Value, propertyType);
                }
            }

            return(dataEntity);
        }
Пример #16
0
        public TDto Update(string id, Action <TDto> action)
        {
            id.GuardAgainstNullOrEmpty(nameof(id));
            action.GuardAgainstNull(nameof(action));

            var entity = this.repository.Retrieve(ContainerName, id,
                                                  RepositoryEntityMetadata.FromType <TDto>());

            if (entity == null)
            {
                throw new ResourceNotFoundException();
            }

            var dto = entity.ToReadModelEntity <TDto>();

            action(dto);
            var updated = this.repository.Replace(ContainerName, id, CommandEntity.FromType(dto));

            this.logger.LogDebug("Updated read model for entity {Id}", id);

            return(updated.ToReadModelEntity <TDto>());
        }
Пример #17
0
        public static List <QueryEntity> JoinResults(this JoinDefinition joinDefinition,
                                                     IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > leftEntities,
                                                     IReadOnlyDictionary <string, IReadOnlyDictionary <string, object> > rightEntities,
                                                     RepositoryEntityMetadata metadata,
                                                     Func <KeyValuePair <string, IReadOnlyDictionary <string, object> >,
                                                           KeyValuePair <string, IReadOnlyDictionary <string, object> >,
                                                           KeyValuePair <string, IReadOnlyDictionary <string, object> > > mapFunc = null)
        {
            switch (joinDefinition.Type)
            {
            case JoinType.Inner:
                var innerJoin = from lefts in leftEntities
                                join rights in rightEntities on lefts.Value[joinDefinition.Left.JoinedFieldName] equals
                                rights.Value[joinDefinition.Right.JoinedFieldName]
                                into joined
                                from result in joined
                                select mapFunc?.Invoke(lefts, result) ?? lefts;

                return(innerJoin
                       .Select(e => EntityFromContainerProperties(e.Value, metadata))
                       .ToList());

            case JoinType.Left:
                var leftJoin = from lefts in leftEntities
                               join rights in rightEntities on lefts.Value[joinDefinition.Left.JoinedFieldName] equals
                               rights.Value[joinDefinition.Right.JoinedFieldName]
                               into joined
                               from result in joined.DefaultIfEmpty()
                               select mapFunc?.Invoke(lefts, result) ?? lefts;

                return(leftJoin
                       .Select(e => EntityFromContainerProperties(e.Value, metadata))
                       .ToList());

            default:
                throw new ArgumentOutOfRangeException(nameof(JoinType));
            }
        }
        private void VerifyConcurrencyCheck(TAggregateRoot aggregate)
        {
            var streamName         = GetEventStreamName(aggregate.Id);
            var eventContainerName = GetEventContainerName();

            var query = Query.From <EntityEvent>().Where(ee => ee.StreamName, ConditionOperator.EqualTo, streamName)
                        .OrderBy(ee => ee.Version).Take(1);
            var latestEvent = this.repository
                              .Query(eventContainerName, query, RepositoryEntityMetadata.FromType <EntityEvent>())
                              .FirstOrDefault();
            var latestStoredVersion = latestEvent == null
                ? 0
                : latestEvent.ToEntity <EntityEvent>(this.domainFactory).Version;

            var loadedVersion = aggregate.ChangeVersion;

            if (latestStoredVersion > loadedVersion)
            {
                throw new ResourceConflictException(
                          Resources.GeneralEventStreamStorage_LoadConcurrencyConflictWritingEventStream.Fmt(streamName,
                                                                                                            loadedVersion));
            }
        }
Пример #19
0
        private static QueryEntity EntityFromContainerProperties(
            this IReadOnlyDictionary <string, object> propertyValues, RepositoryEntityMetadata metadata)

        {
            return(QueryEntity.FromProperties(propertyValues, metadata));
        }
        public TAggregateRoot Load(Identifier id, bool returnNullIfNotFound = false)
        {
            id.GuardAgainstNull(nameof(id));

            var streamName         = GetEventStreamName(id);
            var eventContainerName = GetEventContainerName();

            var events = this.repository.Query(eventContainerName,
                                               Query.From <EntityEvent>()
                                               .Where(ee => ee.StreamName, ConditionOperator.EqualTo, streamName)
                                               .OrderBy(ee => ee.LastPersistedAtUtc), RepositoryEntityMetadata.FromType <EntityEvent>());

            if (!events.Any())
            {
                return(returnNullIfNotFound
                    ? default
                    : RehydrateAggregateRoot(id, null));
            }

            var lastPersistedAtUtc = events.Last().LastPersistedAtUtc;
            var aggregate          = RehydrateAggregateRoot(id, lastPersistedAtUtc);

            aggregate.LoadChanges(events.ConvertAll(@event => @event.ToEntity <EntityEvent>(this.domainFactory)),
                                  this.migrator);

            return(aggregate);
        }
Пример #21
0
        private static string FirstProperty <TQueryableEntity>() where TQueryableEntity : IQueryableEntity
        {
            var metadata = RepositoryEntityMetadata.FromType <TQueryableEntity>();

            return(metadata.Types.First().Key);
        }
Пример #22
0
        private static bool HasProperty <TQueryableEntity>(string propertyName) where TQueryableEntity : IQueryableEntity
        {
            var metadata = RepositoryEntityMetadata.FromType <TQueryableEntity>();

            return(metadata.HasType(propertyName));
        }
Пример #23
0
        public static List <QueryEntity> FetchAllIntoMemory <TQueryableEntity>(this QueryClause <TQueryableEntity> query,
                                                                               IRepository repository,
                                                                               RepositoryEntityMetadata metadata,
                                                                               Func <Dictionary <string, IReadOnlyDictionary <string, object> > > getPrimaryEntities,
                                                                               Func <QueriedEntity, Dictionary <string, IReadOnlyDictionary <string, object> > > getJoinedEntities)
            where TQueryableEntity : IQueryableEntity
        {
            repository.GuardAgainstNull(nameof(repository));
            query.GuardAgainstNull(nameof(query));
            metadata.GuardAgainstNull(nameof(metadata));
            getPrimaryEntities.GuardAgainstNull(nameof(getPrimaryEntities));
            getJoinedEntities.GuardAgainstNull(nameof(getJoinedEntities));

            var take = query.GetDefaultTake(repository);

            if (take == 0)
            {
                return(new List <QueryEntity>());
            }

            var primaryEntities = getPrimaryEntities();

            if (!primaryEntities.HasAny())
            {
                return(new List <QueryEntity>());
            }

            var joinedContainers = query.JoinedEntities
                                   .Where(je => je.Join.Exists())
                                   .ToDictionary(je => je.EntityName, je => new
            {
                Collection   = getJoinedEntities(je),
                JoinedEntity = je
            });

            List <KeyValuePair <string, IReadOnlyDictionary <string, object> > > joinedEntities = null;

            if (!joinedContainers.Any())
            {
                joinedEntities = primaryEntities
                                 .Select(pe => new KeyValuePair <string, IReadOnlyDictionary <string, object> >(pe.Key, pe.Value))
                                 .ToList();
            }
            else
            {
                foreach (var joinedContainer in joinedContainers)
                {
                    var joinedEntity  = joinedContainer.Value.JoinedEntity;
                    var join          = joinedEntity.Join;
                    var rightEntities = joinedContainer.Value.Collection
                                        .ToDictionary(e => e.Key, e => e.Value);

                    joinedEntities = join
                                     .JoinResults(primaryEntities, rightEntities,
                                                  joinedEntity.Selects.ProjectSelectedJoinedProperties());
                }
            }

            var results = joinedEntities?.AsQueryable();
            var orderBy = query.ToDynamicLinqOrderByClause();
            var skip    = query.GetDefaultSkip();

            if (query.Wheres.Any())
            {
                var whereBy = query.Wheres.ToDynamicLinqWhereClause();
                results = results
                          .Where(whereBy);
            }
            return(results
                   .OrderBy(orderBy)
                   .Skip(skip)
                   .Take(take)
                   .Select(sel => new KeyValuePair <string, IReadOnlyDictionary <string, object> >(sel.Key, sel.Value))
                   .CherryPickSelectedProperties(query)
                   .Select(ped => QueryEntity.FromProperties(ped.Value, metadata))
                   .ToList());
        }