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; }
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); }
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); }