protected override sealed async Task PersistModelAsync(PersistEvent @event, TModel model, Graph <TModel> graph, bool create)
        {
            var id         = ModelAnalyzer.GetIdentity(model);
            var streamName = EventStoreCommon.GetStreamName <TModel>(id);

            var eventStoreModel = new EventStoreEventModelData <TModel>()
            {
                Source     = @event.Source,
                SourceType = @event.Source?.GetType().Name,
                Model      = model,
                Graph      = graph
            };

            var data = EventStoreCommon.Serialize(eventStoreModel);

            var eventNumber = await Engine.AppendAsync(@event.ID, @event.Name, streamName, null, create?EventStoreState.NotExisting : EventStoreState.Existing, data);

            if (eventNumber > 0 && eventNumber % SaveStateEvery == 0)
            {
                var thisEventData = (await Engine.ReadBackwardsAsync(streamName, eventNumber, 1, null, null, null))[0];

                var where = ModelAnalyzer.GetIdentityExpression <TModel>(id);

                var eventStates = await Repo.QueryAsync(new EventQueryMany <TModel>(thisEventData.Date, thisEventData.Date, where));

                var eventState = eventStates.Where(x => x.Number == eventNumber).Single();

                await SaveModelStateAsync(id, eventState.Model, eventState.Number);
            }
        }
        private ICollection <EventModel <TModel> > LoadEventModelsFromEventDatas(EventStoreEventData[] eventDatas, TModel modelState, bool many, Query <TModel> query)
        {
            if (modelState == null && eventDatas.Length == 0)
            {
                return(Array.Empty <EventModel <TModel> >());
            }

            if (modelState == null)
            {
                modelState = Instantiator.CreateInstance <TModel>();
            }

            if (many)
            {
                switch (query.TemporalOrder ?? TemporalOrder.Newest)
                {
                case TemporalOrder.Newest:
                {
                    var eventModels = new List <EventModel <TModel> >();
                    foreach (var eventData in eventDatas.Reverse())
                    {
                        var eventModelData = EventStoreCommon.Deserialize <EventStoreEventModelData <TModel> >(eventData.Data.Span);
                        Mapper.MapTo(eventModelData.Model, modelState, eventModelData.Graph);

                        if (query.TemporalDateTo.HasValue && query.TemporalDateTo.Value < eventData.Date)
                        {
                            break;
                        }
                        if (query.TemporalNumberTo.HasValue && query.TemporalNumberTo.Value < eventData.Number)
                        {
                            break;
                        }
                        if ((!query.TemporalDateFrom.HasValue && !query.TemporalNumberFrom.HasValue) || (query.TemporalDateFrom.HasValue && eventData.Date >= query.TemporalDateFrom.Value) || (query.TemporalNumberFrom.HasValue && eventData.Number >= query.TemporalNumberFrom.Value))
                        {
                            var copy       = Mapper.Copy(modelState);
                            var eventModel = new EventModel <TModel>()
                            {
                                EventID   = eventData.EventID,
                                EventName = eventData.EventName,
                                Date      = eventData.Date,
                                Number    = eventData.Number,
                                Deleted   = eventData.Deleted,

                                Model = copy,

                                ModelChange = eventModelData.Model,
                                GraphChange = eventModelData.Graph,
                                Source      = eventModelData.Source,
                                SourceType  = eventModelData.SourceType
                            };
                            eventModels.Add(eventModel);
                        }
                    }
                    if (query.TemporalSkip.HasValue && query.TemporalTake.HasValue)
                    {
                        eventModels.Reverse();
                        return(eventModels.Skip(query.TemporalSkip.Value).Take(query.TemporalTake.Value).Reverse().ToArray());
                    }
                    else if (query.TemporalSkip.HasValue)
                    {
                        eventModels.Reverse();
                        return(eventModels.Skip(query.TemporalSkip.Value).Reverse().ToArray());
                    }
                    else if (query.TemporalTake.HasValue)
                    {
                        eventModels.Reverse();
                        return(eventModels.Take(query.TemporalTake.Value).Reverse().ToArray());
                    }
                    else
                    {
                        return(eventModels);
                    }
                }

                case TemporalOrder.Oldest:
                {
                    var eventModels = new List <EventModel <TModel> >();
                    var skipCount   = 0;
                    foreach (var eventData in eventDatas.Reverse())
                    {
                        var eventModelData = EventStoreCommon.Deserialize <EventStoreEventModelData <TModel> >(eventData.Data.Span);
                        Mapper.MapTo(eventModelData.Model, modelState, eventModelData.Graph);

                        if (query.TemporalDateTo.HasValue && query.TemporalDateTo.Value < eventData.Date)
                        {
                            break;
                        }
                        if (query.TemporalNumberTo.HasValue && query.TemporalNumberTo.Value < eventData.Number)
                        {
                            break;
                        }
                        if ((!query.TemporalDateFrom.HasValue && !query.TemporalNumberFrom.HasValue) || (query.TemporalDateFrom.HasValue && eventData.Date >= query.TemporalDateFrom.Value) || (query.TemporalNumberFrom.HasValue && eventData.Number >= query.TemporalNumberFrom.Value))
                        {
                            if (!query.TemporalSkip.HasValue || query.TemporalSkip.Value <= skipCount)
                            {
                                var copy       = Mapper.Copy(modelState);
                                var eventModel = new EventModel <TModel>()
                                {
                                    EventID   = eventData.EventID,
                                    EventName = eventData.EventName,
                                    Date      = eventData.Date,
                                    Number    = eventData.Number,
                                    Deleted   = eventData.Deleted,

                                    Model = copy,

                                    ModelChange = eventModelData.Model,
                                    GraphChange = eventModelData.Graph,
                                    Source      = eventModelData.Source,
                                    SourceType  = eventModelData.SourceType
                                };
                                eventModels.Add(eventModel);
                            }
                            else
                            {
                                skipCount++;
                            }
                        }
                    }
                    return(eventModels);
                }

                default:
                    throw new NotImplementedException();
                }
            }
            else
            {
                switch (query.TemporalOrder ?? TemporalOrder.Newest)
                {
                case TemporalOrder.Newest:
                {
                    EventStoreEventModelData <TModel> eventModelData = null;
                    EventStoreEventData thisEventData = null;
                    foreach (var eventData in eventDatas.Reverse())
                    {
                        thisEventData  = eventData;
                        eventModelData = EventStoreCommon.Deserialize <EventStoreEventModelData <TModel> >(eventData.Data.Span);
                        Mapper.MapTo(eventModelData.Model, modelState, eventModelData.Graph);

                        if (query.TemporalDateTo.HasValue && query.TemporalDateTo.Value < eventData.Date)
                        {
                            break;
                        }
                        if (!query.TemporalNumberTo.HasValue && eventData.Number < query.TemporalNumberTo.Value)
                        {
                            break;
                        }
                    }
                    var eventModel = new EventModel <TModel>()
                    {
                        EventID   = thisEventData.EventID,
                        EventName = thisEventData.EventName,
                        Date      = thisEventData.Date,
                        Number    = thisEventData.Number,
                        Deleted   = thisEventData.Deleted,

                        Model = modelState,

                        ModelChange = eventModelData.Model,
                        GraphChange = eventModelData.Graph,
                        Source      = eventModelData.Source,
                        SourceType  = eventModelData.SourceType
                    };
                    return(new EventModel <TModel>[] { eventModel });
                }

                case TemporalOrder.Oldest:
                {
                    EventStoreEventModelData <TModel> eventModelData = null;
                    EventStoreEventData thisEventData = null;
                    foreach (var eventData in eventDatas.Reverse())
                    {
                        thisEventData  = eventData;
                        eventModelData = EventStoreCommon.Deserialize <EventStoreEventModelData <TModel> >(eventData.Data.Span);
                        Mapper.MapTo(eventModelData.Model, modelState, eventModelData.Graph);

                        if (!query.TemporalDateFrom.HasValue || eventData.Date >= query.TemporalDateFrom)
                        {
                            break;
                        }
                        if (!query.TemporalNumberFrom.HasValue || eventData.Number >= query.TemporalNumberFrom.Value)
                        {
                            break;
                        }
                    }
                    var eventModel = new EventModel <TModel>()
                    {
                        EventID   = thisEventData.EventID,
                        EventName = thisEventData.EventName,
                        Date      = thisEventData.Date,
                        Number    = thisEventData.Number,
                        Deleted   = thisEventData.Deleted,

                        Model = modelState,

                        ModelChange = eventModelData.Model,
                        GraphChange = eventModelData.Graph,
                        Source      = eventModelData.Source,
                        SourceType  = eventModelData.SourceType
                    };
                    return(new EventModel <TModel>[] { eventModel });
                }

                default:
                    throw new NotImplementedException();
                }
            }
        }