Getting started

Data model

For the example below, I used an ADO.Net Entity Data Model built from the AdventureWorks database (SQLServer sample database : http://msftdbprodsamples.codeplex.com/).

The model includes tables : Production.Product, Production.ProductSubcategory, Production.ProductCategory, Person.Person, Sales.Customer, Sales.SalesOrderDetail, Sales.SalesOrderHeader, Sales.SpecialOfferProduct.

Data model

Define a cube

In your project, open the New Item... dialog and select AdaptiveLINQ C# Cube. You will edit your cube definition using a high level designer integrated in Visual Studio (use Ctrl+Space to open the Intellisens menu).

AdaptiveLINQ cube designer

The Source type is the class of your data model you want to analysis (equivalent vocabulary in OLAP technology is Fact).

A dimension is defined as a lambda expression using an object of source type.
A measure is a aggregation defined as a lambda expression using an enumeration of source type objects.

Type definition generated by cube designer

Each cube definition will be compiled in 2 C# classes:

[CubeName]Defintion
This class expresses the cube definition by holding each expression as a field. It will be the parameter type used by yours .QueryByCube() calls.
[CubeName]Item
This class is the result enumerated type of a .QueryByCube() call.

Classes are defined as partial. So, you can add dimension or measure by defining a partial part of the classes in an other file of the projet.

AdaptiveLINQ cube classes generated

Dynamic property

Warning! This feature doesn't work in free edition mode. See Compare editions.

In some case, dimension or measure can't be defined as static expression.
A common case is the localisation of label. For exemple, the ProductCategory dimension will be expressed differently for French context than for other one.
A dynamic property is a dimension or measure defined as a .Net property instead of a static field.

public partial class SalesCubeDefinition
{
    public SalesCubeDefinition(string lang)
    {
        CurrentLang = lang;
    }
    string CurrentLang;

    public Expression<Func<SalesOrderDetail, string>> LocalizedProductCategory
    {
        get
        {
            if (CurrentLang == "fr")
                return item => item.SpecialOfferProduct.Product.ProductSubcategory.ProductCategory.NameFR;
            else
                return ProductCategory;
        }
    }
}

public partial class SalesCubeItem
{
    /// <summary>
    /// Localized product category label
    /// </summary>
    public string LocalizedProductCategory { get; set; }
}

Use the .QueryByCube() function

Now, you can use .QueryByCube() on any object of type IEnumerable<[SourceType]> or IQueryable<[SourceType]>.

This extension mehod is defined in the AdaptiveLINQ namespace. So, you need to use the using AdaptiveLINQ; statement in the source file where you will use .QueryByCube().

using AdaptiveLINQ;

namespace MyNamespace
{
    class MyClass()
    {
        ...
        IEnumerable<string> GetTopFiveCustomerNamesByProductCategory(string category)
        {
            SalesCubeDefinition myCube = new SalesCubeDefinition();
            IEnumerable<string> result = dataContext.SalesOrderDetail.QueryByCube(myCube)
                .Where(item => item.ProductCategory == category)
                .OrderByDescending(item => item.TotalSales)
                .Take(5)
                .Select(item => item.Customer);
            return result;
        }
        ...