Home
    Shop
    Advertise
    Write For Us
    Affiliate
    Newsletter
    Contact

Dynamic LINQ

LINQ to SQL is an extension of LINQ that allows developers to write "queries" in .NET to retrieve and manipulate data from a SQL Server database. This gives the ability to access relational database objects as normal .Net objects.

 

LINQ to SQL integrates SQL based schema definitions to the common language runtime (CLR) type system. This provides strong typing, syntax checking, intellisense over SQL objects, while retaining the expressive power of the relational model and the performance of query evaluation directly in the underlying database.

LINQ to SQL enables us to write type-safe queries (static SQL Queries ) against an IQueryable objects (SQL data tables). But some times we need to construct the queries dynamically on the fly. Normally we build dynamic SQL queries by concatenating strings together. The same can be achieved in LINQ to SQL using the Dynamic Expression API which extends the core LINQ API capabilities through dynamic construction of expression trees using the classes in the System.Linq.Expressions namespace.

Normally LINQ queries constructed by using language operators or type-safe lambda extension methods. but the dynamic query library provides us with string based extension methods, where we will pass the expressions in string format.

The Dynamic Expression API is present in the System.Linq.Dynamic namespace. This API provides classes:

- Responsible for string-based querying by using IQueryable extension methods.

- Responsible for parsing strings and producing the equivalent expression trees.

- Responsible for generating new classes which represent the Select columns in the dynamically constructed query.



The Dynamic Expression API provides the following IQueryable Extension Methods as part of System.Linq.Dynamic.DynamicQueryable class for dynamically querying objects.

public static IQueryable Where(this IQueryable source,  string predicate, params object[] values);
public static IQueryable<T> Where<T>(this IQueryable<T> source,   string predicate, params object[] values);
public static IQueryable Select(this IQueryable source,    string selector, params object[] values);
public static IQueryable OrderBy(this IQueryable source,    string ordering, params object[] values);
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source,  string ordering, params object[] values);
public static IQueryable Take(this IQueryable source, int count);
public static IQueryable Skip(this IQueryable source, int count);
public static IQueryable GroupBy(this IQueryable source,    string keySelector, string elementSelector, params object[] values);
public static bool Any(this IQueryable source);
public static int Count(this IQueryable source);

These methods operate on IQueryable and use strings instead of lambda expressions to express predicates, selectors, and orderings.

Constructing Dynamic Queries using IQueryable extension Methods

DataClassesDataContext db=new DataClassesDataContext();
var products = from p in db.Products
where p.Model == "SD1000" && p.onsale==true
select p;

We can construct the above query using the IQueryable extension method Where() like below:

DataClassesDataContext db=new  DataClassesDataContext();
 var products = db.Products
     .Where("Model==@0 && onsale==@1","SD1000", true) ;

In the above query Where method is the IQueryable extension method provided in the Dynamic Expression API and takes the input string and produces an equivalent expression tree dynamically to query the products table. Even the string passed to Where method can be constructed dynamically like below

DataClassesDataContext db=new  DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var products = db.Products.Where(condition );

Like the above example we can use the other IQueryable extension methods to construct the queries dynamically according to our programming needs. Some more examples are:

 DataClassesDataContext db=new DataClassesDataContext();
var product = from p in db.Products
where p.Model == "SD1000" && p.onsale == true
orderby p.Name
select new { p.ItemId, p.Name, p.Model1, p.onsale };

That can be converted like below:

DataClassesDataContext db = new DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var products = db.Products
     .Where(condition)
     .OrderBy("Name")
     .Select(" new (ItemId,Name,Model,onsale)");

In the above code the OrderBy extension method is used for ordering the results by Name column and the Select extension method is used for creating the classes dynamically . Observe that the syntax is using '(',')' instead of '{','}' while constructing new classes dynamically as opposed to static class constuction.

The ParseException Class

Normally when constructing dynamic queries by concatenating strings to form an expression string there is a chance of getting parsing errors. The Dynamic Expression API provides ParseException class which can be used to catch the parsing errors. The Position property gives the character index in the expression string at which the parsing error occurred and the message gives the error message.

try
{
DataClassesDataContext db=new DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var products = db.Products
     .Where(condition)
     .OrderBy("Name")
     .Select(" new (ItemId,Name,Model,onsale)");
}
catch (ParseException ex)
{
Response.Write(ex.Position + ex.Message);
}

The Take() extension method is used to select a no of rows from the query result and Skip() extension method is used to skip no of rows from the query result.

DataClassesDataContext db=new DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var product2 = db.Products.Where(condition).OrderBy("Name").Select(" new (ItemId,Name,Model,onsale)").Skip(2).Take(3);

The Count extension method is used to count the no of rows returned as the query result.

DataClassesDataContext db = new DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var count = db.Products.Where(condition).Count();

The GroupBy extension method is used to group the returned results in to IEnumerable groups.

DataClassesDataContext db = new DataClassesDataContext();
var Models= db.Products.GroupBy("Model", "new (Model)");

JOINS in LINQ

There is no direct support for Joins using the extension methods provided in the Dynamic Expression API. However one can use joins indirectly by using inner queries, where the inner queries can be constructed using Dynamic Expression API like below.

DataClassesDataContext db=new DataClassesDataContext();
string condition = "Model==\"SD1000\" && onsale==true ";
var products = from m in (db.Models.Where("Model1==@0", "SD1000"))
join p in (db.Products.Where(condition).OrderBy("Name"))
on m.Model1 equals p.Model
select new { p.ItemId, p.Name, p.Model, m.company, p.Price, p.onsale, p.discount, p.Description, m.features };

While using joins on inner queries, which are constructed using the Dynamic Expression API the Select extension method can't be used on the dynamic queries.

This tutorial is written by RELIANCE CONSULTING.


Tutorial toolbar:  Tell A Friend  |  Add to favorites  |  Feedback  |