Does OData v4 understand Dimensions, Measures and Cubes

720 views Asked by At

I am building an OData Web Service using WebAPI and OData v4.

I am wondering if this new version of OData is capable of understanding Dimension, Measures and Cubes and is able to execute Queries from the data.

How would I be able to configure that?

2

There are 2 answers

4
Yi Ding - MSFT On

From the Overview of the protocol spec you can see that:

Towards that end, the OData Protocol follows these design principles: Prefer mechanisms that work on a variety of data stores. In particular, do not assume a relational data model.

So there isn't anything preventing you from modelling cube data using OData.

One way that I can think of is to consider every entity set as a cube, in which some properties & navigation properties of each entity are the dimensions it has. And it has a bunch of measure properties as its measures. Thus, by querying the entity set, you get the whole cube. And you can use some simple query to query it:

GET http://host/service/Cube?$select=Dimension1,Dimension2,Measure1 & $filter=Measure1 gt 100

This is only my own simple model. For more complicated cube representation and queryability, OData V4 has this aggregation extension to help you better modelling it. You can have a look at this example data model it has to modelling cube data.

2
nlips On

Using the LINQ extension method QueryByCube provide by the AdaptiveLINQ component, you can develop a queryable analysis service.

Sample LINQ query using QueryByCube:

dataContext.MyEntitySet.QueryByCube(myCube)
    .Where(x => x.Measure1 > 100)
    .Select(x => new {
       Dimension1 = x.Dimension1,
       Dimension2 = x.Dimension2,
       Measure1 = x.Meeasure1
    })

QueryByCube acts as a (queryable) view with implicit aggregations.

Cube dimensions and measures are defined as C# expression. myCube is a instance of a class implementing the AdaptiveLINQ.ICubeDefinition<> interface.

public class MyCubeDefinition : ICubeDefinition<MySourceClass, MyCubeItem>
{
  static public readonly Expression<Func<MySourceClass, string>>
    Dimension1 = item => ...
  static public readonly Expression<Func<MySourceClass, string>>
    Dimension2 = item => ...
  static public readonly Expression<Func<IEnumerbale<MySourceClass>, string>>
    Measure1 = items => ...
}

QueryByCube transforms the query (based on a semantic analysis to determine the dimensions to be used) in order to use the GroupBy operator and return an IQueryable collection.

To expose the cube as a queryable HTTP service, implement an ASP.Net WebAPI ODataController like this:

public class MyCubeController : ODataController
{
  public MyCubeController()
  {
    // get dataContext
    ...
  }

  static MyCubeDefinition MyCube = new MyCubeDefinition();

  [EnableQuery]
  public IQueryable<MyCubeItem> Get()
  {
      return dataContext.MyEntitySet.QueryByCube(myCube);       
  }
}

Now you can query your cube like this:

Mesaure1 per Dimension1

http://.../MyCube?$select=Dimension1, Measure1

Mesaure1 per (Dimension1, Dimension2)

http://.../MyCube?$select=Dimension1, Dimension2, Measure1

Mesaure1 per (Dimension1, Dimension2) order by Mesaure1, top 5

http://.../MyCube?$select=Dimension1, Dimension2, Measure1&$orderby=Measure1&$top=5

Disclaimer: I'm the AdaptiveLINQ developer