public void HandleSubscription(CollectionSubscription subscription, Type dbContextType,
                                       IServiceProvider requestServiceProvider, ConnectionBase connection, KeyValuePair <Type, string> property,
                                       List <ChangeResponse> collectionChanges, List <ChangeResponse> allChanges)
        {
            try
            {
                bool anyCollectionChanges = collectionChanges.Any();

                if ((anyCollectionChanges && subscription.Prefilters.Any(prefilter =>
                                                                         prefilter is IAfterQueryPrefilter || prefilter is TakePrefilter || prefilter is SkipPrefilter)) ||
                    HasIncludePrefilterWithChange(subscription, allChanges))
                {
                    SapphireDbContext db = dbContextAccessor.GetContext(dbContextType, requestServiceProvider);

                    IQueryable <object> collectionValues = db.GetCollectionValues(requestServiceProvider,
                                                                                  connection.Information, property, subscription.Prefilters);

                    IAfterQueryPrefilter afterQueryPrefilter =
                        subscription.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault();

                    if (afterQueryPrefilter != null)
                    {
                        afterQueryPrefilter.Initialize(property.Key);

                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = afterQueryPrefilter.Execute(collectionValues)
                        });
                    }
                    else
                    {
                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = collectionValues
                                          .AsEnumerable()
                                          .Select(v => v.GetAuthenticatedQueryModel(connection.Information, serviceProvider))
                                          .ToList()
                        });
                    }
                }
                else if (anyCollectionChanges)
                {
                    IEnumerable <WherePrefilter> wherePrefilters = subscription.Prefilters.OfType <WherePrefilter>();

                    foreach (WherePrefilter wherePrefilter in wherePrefilters)
                    {
                        wherePrefilter.Initialize(property.Key);
                        Func <object, bool> whereFunction = wherePrefilter.WhereExpression.Compile();
                        collectionChanges = collectionChanges.Where((change) => whereFunction(change.Value)).ToList();
                    }

                    collectionChanges.ForEach(change =>
                    {
                        object value =
                            change.Value.GetAuthenticatedQueryModel(connection.Information, requestServiceProvider);
                        _ = connection.Send(change.CreateResponse(subscription.ReferenceId, value));
                    });
                }
            }
            catch (Exception ex)
            {
                SubscribeCommand tempErrorCommand = new SubscribeCommand()
                {
                    CollectionName = subscription.CollectionName,
                    ReferenceId    = subscription.ReferenceId,
                    Prefilters     = subscription.Prefilters
                };

                _ = connection.Send(tempErrorCommand.CreateExceptionResponse <ResponseBase>(ex));
                logger.LogError(
                    $"Error handling subscription '{subscription.ReferenceId}' of {subscription.CollectionName}");
                logger.LogError(ex.Message);
            }
        }
        public void HandleSubscription(CollectionSubscription subscription, Type dbContextType,
                                       IServiceProvider requestServiceProvider, ConnectionBase connection, KeyValuePair <Type, string> property,
                                       List <ChangeResponse> collectionChanges, List <ChangeResponse> allChanges)
        {
            try
            {
                bool anyCollectionChanges = collectionChanges.Any();

                if ((anyCollectionChanges && subscription.Prefilters.Any(prefilter =>
                                                                         prefilter is IAfterQueryPrefilter || prefilter is TakePrefilter || prefilter is SkipPrefilter)) ||
                    HasIncludePrefilterWithChange(subscription, allChanges))
                {
                    SapphireDbContext db = dbContextAccessor.GetContext(dbContextType, requestServiceProvider);

                    IQueryable <object> collectionValues = db.GetCollectionValues(requestServiceProvider,
                                                                                  connection.Information, property, subscription.Prefilters);

                    IAfterQueryPrefilter afterQueryPrefilter =
                        subscription.Prefilters.OfType <IAfterQueryPrefilter>().FirstOrDefault();

                    if (afterQueryPrefilter != null)
                    {
                        afterQueryPrefilter.Initialize(property.Key);

                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = afterQueryPrefilter.Execute(collectionValues)
                        });
                    }
                    else
                    {
                        _ = connection.Send(new QueryResponse()
                        {
                            ReferenceId = subscription.ReferenceId,
                            Result      = collectionValues
                                          .AsEnumerable()
                                          .Select(v => v.GetAuthenticatedQueryModel(connection.Information, serviceProvider))
                                          .ToList()
                        });
                    }
                }
                else if (anyCollectionChanges)
                {
                    IEnumerable <WherePrefilter> wherePrefilters = subscription.Prefilters.OfType <WherePrefilter>();

                    List <ChangeResponse> oldValuesUnloadResponses = new List <ChangeResponse>();
                    List <ChangeResponse> newValuesLoadResponses   = new List <ChangeResponse>();

                    foreach (WherePrefilter wherePrefilter in wherePrefilters)
                    {
                        wherePrefilter.Initialize(property.Key);

                        // Values that did change know do match the
                        oldValuesUnloadResponses.AddRange(
                            collectionChanges
                            .Where(change => change.State == ChangeResponse.ChangeState.Modified &&
                                   !wherePrefilter.WhereExpressionCompiled(change.Value) &&
                                   wherePrefilter.WhereExpressionCompiled(change.OriginalValue))
                            .Select(change =>
                        {
                            ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value);
                            newChangeResponse.State          = ChangeResponse.ChangeState.Deleted;
                            return(newChangeResponse);
                        })
                            );

                        newValuesLoadResponses.AddRange(
                            collectionChanges
                            .Where(change => change.State == ChangeResponse.ChangeState.Modified &&
                                   wherePrefilter.WhereExpressionCompiled(change.Value) &&
                                   !wherePrefilter.WhereExpressionCompiled(change.OriginalValue))
                            .Select(change =>
                        {
                            ChangeResponse newChangeResponse = change.CreateResponse(null, change.Value);
                            newChangeResponse.State          = ChangeResponse.ChangeState.Added;
                            return(newChangeResponse);
                        })
                            );

                        collectionChanges = collectionChanges
                                            .Where((change) => wherePrefilter.WhereExpressionCompiled(change.Value)).ToList();
                    }

                    IEnumerable <ChangeResponse> changesForWherePrefilter = oldValuesUnloadResponses
                                                                            .Concat(newValuesLoadResponses)
                                                                            .GroupBy(v => v.Value)
                                                                            .Select(g => g.LastOrDefault());

                    collectionChanges = collectionChanges.Concat(changesForWherePrefilter).ToList();

                    ChangesResponse changesResponse = new ChangesResponse()
                    {
                        ReferenceId = subscription.ReferenceId,
                        Changes     = collectionChanges.Select(change =>
                        {
                            object value =
                                change.Value.GetAuthenticatedQueryModel(connection.Information, requestServiceProvider);
                            return(change.CreateResponse(subscription.ReferenceId, value));
                        }).ToList()
                    };

                    if (changesResponse.Changes.Any())
                    {
                        _ = connection.Send(changesResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                SubscribeCommand tempErrorCommand = new SubscribeCommand()
                {
                    CollectionName = subscription.CollectionName,
                    ReferenceId    = subscription.ReferenceId,
                    Prefilters     = subscription.Prefilters
                };

                _ = connection.Send(tempErrorCommand.CreateExceptionResponse <ResponseBase>(ex));
                logger.LogError(
                    $"Error handling subscription '{subscription.ReferenceId}' of {subscription.CollectionName}");
                logger.LogError(ex.Message);
            }
        }