Exemple #1
0
        public Task<List<SerializableDynamicObject>> GetDataAsync(Query query)
        {
            var request = new GetDataRequest
            {
                Query = query
            };

            return _requestTask.Get(request)
                               .Select(x => x.Results.ToList(), _scheduler.Task.TPL);
        }
        public void ProductEntityGroupByProductName()
        {
            // new(Key.ProductName as ProductName,
            // Sum(UnitPrice) as UnitPrice,
            // Sum(UnitsInStock) as UnitsInStock,
            // Sum(UnitsOnOrder) as UnitsOnOrder,
            // Sum(ReorderLevel) as ReorderLevel
            var entity = new Entity("Products");
            var dimension = new Dimension("ProductName");
            entity.Dimensions.Add(dimension);
            entity.Measures.Add(new Measure("UnitPrice"));
            entity.Measures.Add(new Measure("UnitsInStock"));
            entity.Measures.Add(new Measure("UnitsOnOrder"));
            entity.Measures.Add(new Measure("ReorderLevel"));

            var query = new Query
            {
                DataSource = new DataSource {Name = "Northwind"},
                Entity = entity,
                GroupingDimensions = new[] {dimension},
            };

            var entityFrameworkQueryExecutor = new EntityFrameworkQueryExecutor().Execute(new MyDbContext(), query);
        }
        public List<SerializableDynamicObject> Execute(DbContext dbContext, Query query)
        {
            var results = new List<SerializableDynamicObject>();

            using (var context = dbContext)
            {
                context.Database.Log = s => Console.WriteLine(string.Format("EFApp : {0}", s));

                var entityProperty = context.GetType()
                    .GetProperties()
                    .FirstOrDefault(x => x.Name == query.Entity.Name);

                if (entityProperty == null)
                {
                    return results;
                }

                var entity = entityProperty.GetValue(context, null) as IQueryable;
                if (entity == null)
                {
                    return results;
                }

                var data = entity;

                if (query.Filters.Any())
                {
                    data = ExecuteWhere(data, query);
                }

                var keySelector = BuildKeySelector(query);

                var selector = BuildSelector(query);

                data = data
                    .GroupBy(keySelector, "it")
                    .Select(selector);

                var groupingDimensionProperties = new Dictionary<Dimension, PropertyInfo>();
                var measureProperties = new Dictionary<Measure, PropertyInfo>();

                // To enable original order to be reserved
                long recordIndex = 0;
                foreach (var record in data)
                {
                    if (!groupingDimensionProperties.Any() && !measureProperties.Any())
                    {
                        var type = record.GetType();
                        var properties = type.GetProperties();

                        foreach (var dimension in query.GroupingDimensions)
                        {
                            groupingDimensionProperties.Add(dimension, properties.Single(x => x.Name == dimension.Name));
                        }

                        foreach (var measure in query.Entity.Measures)
                        {
                            measureProperties.Add(measure, properties.Single(x => x.Name == measure.Name));
                        }
                    }

                    var result = new SerializableDynamicObject();

                    foreach (var groupingDimensionProperty in groupingDimensionProperties)
                    {
                        result.SetValue(groupingDimensionProperty.Key.Name, groupingDimensionProperty.Value.GetValue(record, null));
                    }

                    foreach (var measureProperty in measureProperties)
                    {
                        result.SetValue(measureProperty.Key.Name, measureProperty.Value.GetValue(record, null));
                    }

                    result.SetValue("RecordIndex", recordIndex);
                    recordIndex++;

                    results.Add(result);
                }
            }

            return results;
        }
        private static IQueryable ExecuteWhere(IQueryable data, Query query)
        {
            var result = data;

            foreach (var filter in query.Filters)
            {
                result = data.Where(string.Format("{0} {1} @0",
                                                  filter.Dimension.Name,
                                                  GetFilterOperator(filter.Operator)),
                                    filter.Value);
            }

            return result;
        }
        private static string BuildSelector(Query query)
        {
            var groupingDimensionSelector =
                string.Join(",", query.GroupingDimensions.Select(x => string.Format("Key.{0} as {0}", x.Name)));
            var measureSelector = string.Join(",",
                query.Entity.Measures.Select(x => string.Format("Sum({0}) as {0}", x.Name)));

            var selectorBuilder = new StringBuilder();
            selectorBuilder.Append("new(");
            selectorBuilder.Append(groupingDimensionSelector);
            if (query.Entity.Measures.Any())
            {
                selectorBuilder.Append(",");
                selectorBuilder.Append(measureSelector);
            }
            selectorBuilder.Append(")");
            var selector = selectorBuilder.ToString();
            return selector;
        }
        private static string BuildKeySelector(Query query)
        {
            var groupingDimensionKeySelector =
                string.Join(", ",
                    query.GroupingDimensions.Select(x => string.Format("{0}", x.Name)));

            var keySelectorBuilder = new StringBuilder();
            keySelectorBuilder.Append("new(");
            keySelectorBuilder.Append(groupingDimensionKeySelector);
            keySelectorBuilder.Append(")");
            var keySelector = keySelectorBuilder.ToString();
            return keySelector;
        }
        public ExplorerViewModel(ILog log, IDispatcherSchedulerProvider scheduler, IStandardDialog standardDialog, 
                                 IExplorerService service,
                                 DataSourceSelectorViewModel dataSourceSelectorViewModel,
                                 SearchViewModel searchViewModel,
                                 DataViewModel dataViewModel,
                                 FilterViewModel filterViewModel,
                                 PathViewModel pathViewModel,
                                 Func<PathItemViewModel> pathItemViewModelFactory)
            : base(log, scheduler, standardDialog)
        {
            _service = service;
            _pathItemViewModelFactory = pathItemViewModelFactory;

            Disposables.Add(service);

            this.SetupHeader(Scheduler, "Explorer");

            DataSourceSelectorViewModel = dataSourceSelectorViewModel;
            this.SyncViewModelActivationStates(DataSourceSelectorViewModel).AddDisposable(Disposables);
            this.SyncViewModelBusy(DataSourceSelectorViewModel).AddDisposable(Disposables);

            SearchViewModel = searchViewModel;
            this.SyncViewModelActivationStates(SearchViewModel).AddDisposable(Disposables);
            this.SyncViewModelBusy(SearchViewModel).AddDisposable(Disposables);

            DataViewModel = dataViewModel;
            this.SyncViewModelActivationStates(DataViewModel).AddDisposable(Disposables);
            this.SyncViewModelBusy(DataViewModel).AddDisposable(Disposables);

            FilterViewModel = filterViewModel;
            this.SyncViewModelActivationStates(FilterViewModel).AddDisposable(Disposables);
            this.SyncViewModelBusy(FilterViewModel).AddDisposable(Disposables);

            PathViewModel = pathViewModel;
            this.SyncViewModelActivationStates(PathViewModel).AddDisposable(Disposables);
            this.SyncViewModelBusy(PathViewModel).AddDisposable(Disposables);

            // When the selected DataSource changes, keep the Search upto date.
            DataSourceSelectorViewModel.DataSources.SelectedItemChanged
                                       .Where(x => x != null)
                                       .SelectMany(dataSource => SearchViewModel.Reset(dataSource).ToObservable())
                                       .TakeUntil(ClosingStrategy.Closed)
                                       .Subscribe(_ => { });

            // When the selected Dimension changes, create a new root level path node with the correct query.
            SearchViewModel.Dimension.SelectedItemChanged
                           .Where(x => x != null)
                           .TakeUntil(ClosingStrategy.Closed)
                           .ObserveOn(Scheduler.Dispatcher.RX)
                           .Subscribe(_ =>
                                      {
                                          var query = new Query
                                                      {
                                                          DataSource = DataSourceSelectorViewModel.DataSources.SelectedItem,
                                                          Entity = SearchViewModel.Entity.SelectedItem,
                                                          GroupingDimensions = new[] {SearchViewModel.Dimension.SelectedItem},
                                                          ParentQuery = null
                                                      };

                                          var pathItem = _pathItemViewModelFactory();
                                          pathItem.DisplayText = query.GroupingDimensions.First().Name;
                                          pathItem.Query = query;

                                          PathViewModel.Path.Items.Add(pathItem);
                                          PathViewModel.Path.SelectedItem = pathItem;
                                      });

            // When a DrillDownDimensionRequest is recieved, create a new path node under the currectly selected
            // node.
            DataViewModel.DrillDownDimensionRequest
                         .Where(x => x != null)
                         .TakeUntil(ClosingStrategy.Closed)
                         .ObserveOn(Scheduler.Dispatcher.RX)
                         .Subscribe(query =>
                                    {
                                        var pathItem = _pathItemViewModelFactory();
                                        pathItem.DisplayText = query.GroupingDimensions.First().Name;
                                        pathItem.Query = query;

                                        PathViewModel.Path.SelectedItem.AddChild(pathItem);
                                        PathViewModel.Path.SelectedItem = pathItem;
                                    });

            // As the SelectedPathItem changes, keep the Data upto date.
            PathViewModel.Path.SelectedItemChanged
                         .Where(x => x != null)
                         .SelectMany(x => GetData(x.Query))
                         .TakeUntil(ClosingStrategy.Closed)
                         .Subscribe(_ => { });
        }
 private IObservable<Query> GetData(Query query)
 {
     var dimensionsAvailable = SearchViewModel.Entity.SelectedItem.Dimensions
                                              .Except(GetExistingQueryDimensions(query))
                                              .ToList();
     return DataViewModel.Reset(query, dimensionsAvailable).ToObservable();
 }
        private static IEnumerable<Dimension> GetExistingQueryDimensions(Query query)
        {
            var results = query.GroupingDimensions.AsEnumerable();

            if (query.ParentQuery != null)
            {
                results = results.Concat(GetExistingQueryDimensions(query.ParentQuery));
            }

            return results;
        }
Exemple #10
0
        private Task SetupContextMenu(Query query, IEnumerable<Dimension> dimensionsAvailable)
        {
            // Only show Dimensions that haven't been grouped by.
            var dimensionContextMenuItems = dimensionsAvailable
                .Where(x => !query.GroupingDimensions.Contains(x))
                .Select(x =>
                        new ContextMenuButtonItem(Scheduler)
                        {
                            DisplayName = x.Name,
                            Command = new DelegateCommand(
                                () =>
                                {
                                    var selectedDimension = dimensionsAvailable
                                        .SingleOrDefault(d => d.Name == x.Name);
                                    if (selectedDimension == null)
                                    {
                                        return;
                                    }

                                    //var selectedItem = Items[SelectedItemIndex];

                                    var newFilter = query.GroupingDimensions
                                        .Select(d => new Nitrogen.Common.DataExplorer.Filter
                                                     {
                                                         Dimension = d,
                                                         Operator = FilterOperator.Equals,
                                                         Value = SelectedItem[d.Name]
                                                     })
                                        .ToList();

                                    var newQuery = query.DrillDown(new[] {selectedDimension}, newFilter);

                                    _drillDownDimensionRequest.OnNext(newQuery);
                                })
                        });

            return ContextMenu.AddRangeAsync(dimensionContextMenuItems);
        }
Exemple #11
0
        public Task<Query> Reset(Query query, IEnumerable<Dimension> dimensionsAvailable)
        {
            return ContextMenu.ClearAsync()
                              .Then(() => SetupContextMenu(query, dimensionsAvailable), Scheduler.Task.TPL)
                              .Then(() => _service.GetDataAsync(query), Scheduler.Task.TPL)
                              .Then(data =>
                                    {
                                        // TODO : This is not great. Change grid to support CollectionChanges
                                        Columns = null;
                                        Items = null;

                                        if (!data.Any())
                                        {
                                            return query;
                                        }

                                        var records = TransformSerializableDynamicObjectToDictionary(data);

                                        var items = _itemsCollectionFactory();
                                        items.AddRange(records);
                                        Items = items;

                                        var columns = _columnCollectionFactory();
                                        columns.AddRange(GetColumns(records));
                                        Columns = columns;

                                        return query;
                                    }, Scheduler.Dispatcher.TPL);
        }