C# .NET - Regarding PredicateBuilder.True<>

Asked By Arvind Subramani
27-Aug-11 02:49 AM
Hi guys!,
What is the use of it?
PredicateBuilder.True<>
  aneesa replied to Arvind Subramani
27-Aug-11 03:09 AM

Dynamically Composing Expression Predicates

Suppose you want to write a LINQ to SQL or Entity Framework query that implements a keyword-style search. In other words, a query that returns rows whose description contains some or all of a given set of keywords.

We can proceed as follows:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  IQueryable<Product> query = dataContext.Products;

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    query = query.Where (p => p.Description.Contains (temp));
  }
  return query;
}

The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreach loop.

So far, so good. But this only handles the case where you want to match all of the specified keywords. Suppose instead, we wanted products whose description contains any of the supplied keywords. Our previous approach of chaining Where operators is completely useless! We could instead chain Union operators, but this would be inefficient. The ideal approach is to dynamically construct a lambda expression tree that performs an or-based predicate.

Of all the things that will drive you to manually constructing expression trees, the need for dynamic predicates is the most common in a typical business application. Fortunately, it’s possible to write a set of simple and reusable extension methods that radically simplify this task. This is the role of our PredicateBuilder class.

Using PredicateBuilder

Here's how to solve the preceding example with PredicateBuilder:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}

If querying with Entity Framework, change the last line to this:

return objectContext.Products.AsExpandable().Where (predicate);

The AsExpandable method is part of http://www.albahari.com/nutshell/linqkit.aspx (see below).

The easiest way to experiment with PredicateBuilder is with http://www.linqpad.net/. LINQPad lets you instantly test LINQ queries against a database or local collection and has direct support for PredicateBuilder (press F4 and check 'Include PredicateBuilder').

PredicateBuilder Source Code

Here's the complete source:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
 
public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }
 
  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }
 
  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

PredicateBuilder is also shipped as part of http://www.albahari.com/nutshell/linqkit.aspx, a productivity kit for LINQ to SQL and Entity Framework.

If you're using LINQ to SQL, you can use the PredicateBuilder source code on its own.

If you're using Entity Framework, you'll need the complete http://www.albahari.com/nutshell/linqkit.aspx - for the AsExpandable functionality. You can either reference LINQKit.dll or copy LINQKit's source code into your application.

How it Works

The True and False methods do nothing special: they are simply convenient shortcuts for creating an Expression<Func<T,bool>> that initially evaluates to true or false. So the following:

var predicate = PredicateBuilder.True <Product> ();

is just a shortcut for this:

Expression<Func<Product, bool>> predicate = c => true;

When you’re building a predicate by repeatedly stacking and/or conditions, it’s useful to have a starting point of either true or false (respectively). Our SearchProducts method still works if no keywords are supplied.

The interesting work takes place inside the And and Or methods. We start by invoking the second expression with the first expression’s parameters. An Invoke expression calls another lambda expression using the given expressions as arguments. We can create the conditional expression from the body of the first expression and the invoked version of the second. The final step is to wrap this in a new lambda expression.

Entity Framework's query processing pipeline cannot handle invocation expressions, which is why you need to call AsExpandable on the first object in the query. By calling AsExpandable, you activate LINQKit's expression visitor class which substitutes invocation expressions with simpler constructs that Entity Framework can understand.

More Examples

A useful pattern in writing a data access layer is to create a reusable predicate library. Your queries, then, consist largely of select and orderby clauses, the filtering logic farmed out to your library. Here's a simple example:

public partial class Product
{
  public static Expression<Func<Product, bool>> IsSelling()
  {
    return p => !p.Discontinued && p.LastSale > DateTime.Now.AddDays (-30);
  }
}

We can extend this by adding a method that uses PredicateBuilder:

public partial class Product
{
  public static Expression<Func<Product, bool>> ContainsInDescription (
                                                params string[] keywords)
  {
    var predicate = PredicateBuilder.False<Product>();
    foreach (string keyword in keywords)
    {
      string temp = keyword;
      predicate = predicate.Or (p => p.Description.Contains (temp));
    }
    return predicate;
  }
}

This offers an excellent balance of simplicity and reusability, as well as separating business logic from expression plumbing logic. To retrieve all products whose description contains “BlackBerry” or “iPhone”, along with the Nokias and Ericssons that are selling, you would do this:

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                      .And (Product.IsSelling());
var query =
  from p in Data.Products.Where (newKids.Or (classics))
  select p;

The And and Or methods in boldface resolve to extension methods in PredicateBuilder.
An expression predicate can perform the equivalent of an SQL subquery by referencing association properties. So, if Product had a child EntitySet called Purchases, we could refine our IsSelling method to return only those products that have sold a minimum number of units as follows:

public static Expression<Func<Product, bool>> IsSelling (int minPurchases)
{
  return prod =>
    !prod.Discontinued &&
     prod.Purchases.Where (purch => purch.Date > DateTime.Now.AddDays(-30))
                    .Count() >= minPurchases;
}

Nesting Predicates

Consider the following predicate:

p => p.Price > 100 &&
     p.Price < 1000 &&
     (p.Description.Contains ("foo") || p.Description.Contains ("far"))

Let's say we wanted to build this dynamically. The question is, how do we deal with the parenthesis around the two expressions in the last line?

The answer is to build the parenthesised expression first, and then consume it in the outer expression as follows:

var inner = PredicateBuilder.False<Product>();
inner = inner.Or (p => p.Description.Contains ("foo"));
inner = inner.Or (p => p.Description.Contains ("far"));

var outer = PredicateBuilder.True<Product>();
outer = outer.And (p => p.Price > 100);
outer = outer.And (p => p.Price < 1000);
outer = outer.And (inner);

Notice that with the inner expression, we start with PredicateBuilder.False (because we're using the Or operator). With the outer expression, however, we start with PredicateBuilder.True (because we're using the And operator).

Generic Predicates

Suppose every table in your database has ValidFrom and ValidTo columns as follows:

create table PriceList
(
   ID int not null primary key,
   Name nvarchar(50) not null,
   ValidFrom datetime,
   ValidTo datetime
)

To retrieve rows valid as of DateTime.Now (the most common case), you'd do this:

from p in PriceLists
where (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
      (p.ValidTo   == null || p.ValidTo   >= DateTime.Now)
select p.Name

Of course, that logic in bold is likely to be duplicated across multiple queries! No problem: let's define a method in the PriceList class that returns a reusable expression:

public static Expression<Func<PriceList, bool>> IsCurrent()
{
   return p => (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
               (p.ValidTo   == null || p.ValidTo   >= DateTime.Now);
}

OK: our query is now much simpler:

var currentPriceLists = db.PriceLists.Where (PriceList.IsCurrent());

And with PredicateBuilder's And and Or methods, we can easily introduce other conditions:

var currentPriceLists = db.PriceLists.Where (
                          PriceList.IsCurrent().And (p => p.Name.StartsWith ("A")));

But what about all the other tables that also have ValidFrom and ValidTo columns? We don't want to repeat our IsCurrent method for every table! Fortunately, we can generalize our IsCurrent method with generics.

The first step is to define an interface:

public interface IValidFromTo
{
   DateTime? ValidFrom { get; }
   DateTime? ValidTo   { get; }
}

Now we can define a single generic IsCurrent method using that interface as a constraint:

public static Expression<Func<TEntity, bool>> IsCurrent<TEntity>()
   where TEntity : IValidFromTo
{
   return e => (e.ValidFrom == null || e.ValidFrom <= DateTime.Now) &&
               (e.ValidTo   == null || e.ValidTo   >= DateTime.Now);
}

The final step is to implement this interface in each class that supports ValidFrom and ValidTo. If you're using Visual Studio or a tool like SqlMetal to generate your entity classes, do this in the non-generated half of the partial classes:

public partial class PriceList : IValidFromTo { }
public partial class Product   : IValidFromTo { }

Using PredicateBuilder within LINQPad

With http://www.linqpad.net/, you can write and test queries much faster than with Visual Studio's build/run/debug cycle. To use PredicateBuilder in LINQPad with LINQ to SQL:

  • Press F4 and check 'Include PredicateBuilder'

To use PredicateBuilder in LINQPad with Entity Framework:

  • Press F4 and add a reference to http://www.albahari.com/nutshell/linqkit.aspx
  Arvind Subramani replied to aneesa
27-Aug-11 03:28 AM
ya Aneesa thanks .but can u  give simple and short tips ?
  aneesa replied to Arvind Subramani
27-Aug-11 03:57 AM

Introduction

LINQ to SQL allow user to query data from the database without writing sql queries by writing LINQ queries. LINQ represent each table as one entity and where LINQ queries allows to manipulate data in type safe.But Static LINQ queries not able to meet all our programming needs. A Dynamic LINQ queries is needed when we need to retrieve a set of records based on different search parameters.

For example - An employee search screen or a general purpose report which needs to execute a different SELECT statement based on a different WHERE as well as Sorting column to sort data.

Dynamic query in Sql server

In SQL there is concept of dynamic queries which allow to write and execute dynamic queries easily. In SQL server we use EXECUTE or sp_executesql to execute dynamic query.

Example:

DECLARE @SQLQuery AS NVARCHAR(500)
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = + convert(@EmpID as varchar(10))
EXECUTE(@SQLQuery) 

We could compose above query as like below as well,

DECLARE @SQLQuery AS NVARCHAR(500)
DECLARE @ParameterDefinition AS NVARCHAR(100)
DECLARE @EmpID INT
SET @EmpID =100
SET @SQLQuery = 'SELECT * FROM tblEmployees WHERE EmployeeID = @EmpID'
SET @ParameterDefinition =  '@EmpID INT'
EXECUTE sp_executesql @SQLQuery, @ParameterDefinition, @EmpID

Now Question is , how to do create same query when you are use the LINQ?,There are two ways to implement,

1. Use Dynamic LINQ libarary
2. Use PredicateBuilder

To understand both of the above library consider the below screen shot

Image Loading

I want to search data by entering in above screen. Note here I may left some field blank and some field filled with value.

1.Use Dynamic LINQ library

Dynamic LINQ library allows build query which are having varying where clause or orderby. To work with the dynamic LINQ library you need to download and install file in your project.
you get the file from this link : http://www.scottgu.com/blogposts/dynquery/dynamiclinqcsharp.zip

so once you install the file you can build query as we can do in pl-sql query.Following code demonstrate how to build where dynamically

string strWhere = string.Empty;
        string strOrderBy = string.Empty;
 
        if (!string.IsNullOrEmpty(txtAddress.Text))
            strWhere = "Address.StartsWith(\"" + txtAddress.Text + "\")"; 
        if (!string.IsNullOrEmpty(txtEmpId.Text))
        {
            if(!string.IsNullOrEmpty(strWhere ))
                strWhere = " And ";
            strWhere = "Id = " + txtEmpId.Text;
        }
        if (!string.IsNullOrEmpty(txtDesc.Text))
        {
            if (!string.IsNullOrEmpty(strWhere))
                strWhere = " And ";
            strWhere = "Desc.StartsWith(\"" + txtDesc.Text + "\")";
        }
        if (!string.IsNullOrEmpty(txtName.Text))
        {
            if (!string.IsNullOrEmpty(strWhere))
                strWhere = " And ";
            strWhere = "Name.StartsWith(\"" + txtName.Text + "\")";
        }
 
        EmployeeDataContext edb = new EmployeeDataContext();
        var emp = edb.Employees.Where(strWhere);
        grdEmployee.DataSource = emp.ToList();
        grdEmployee.DataBind();

In above code I am building strWhere dynamically because there may be some criteria no have value where some has.

2.Predicate Builder

Predicate builder works same as dynamic linq library but the main difference is its allow to write more type safe queries easily.You can get the detail about predicate builder form here : http://www.albahari.com/nutshell/predicatebuilder.aspx.

Following code shows how you can use PredicateBuilder easily to create dynamic clause easily.

var predicate = PredicateBuilder.True<employee>();
 
        if(!string.IsNullOrEmpty(txtAddress.Text))
            predicate = predicate.And(e1 => e1.Address.Contains(txtAddress.Text));
        if (!string.IsNullOrEmpty(txtEmpId.Text))
            predicate = predicate.And(e1 => e1.Id == Convert.ToInt32(txtEmpId.Text));
        if (!string.IsNullOrEmpty(txtDesc.Text))
            predicate = predicate.And(e1 => e1.Desc.Contains(txtDesc.Text));
        if (!string.IsNullOrEmpty(txtName.Text))
            predicate = predicate.And(e1 => e1.Name.Contains(txtName.Text));
 
        EmployeeDataContext edb= new EmployeeDataContext();
        var emp = edb.Employees.Where(predicate);
        grdEmployee.DataSource = emp.ToList();
        grdEmployee.DataBind();
</employee>

So as you see in above code I had created one PredicateBuilder for AND condition and building where clause same way you can build OR clause by using PredicateBuilder.

Difference between both library

  1. Predicatebuilder allows to build TypeSafe dynamic queries.
  2. Dynamic LINQ library allows to builder query with the Dynamic ORDER BY clause.

 

  Anoop S replied to Arvind Subramani
27-Aug-11 04:04 AM
What’s a “predicate”?

A “predicate” is a function that examines some input and returns true or false.

The code fragment, “p => p.ProductName.Contains(“Sir”)” , is a predicate that examines a product and returns true if the product’s ProductName contains the “Sir” string.

The CLR type of the predicate in our example is:

Func<Product, bool>

Which we can generalize to:

Func<T, bool>

Using PredicateBuilder

Here's how to solve the preceding example with PredicateBuilder:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}

If querying with Entity Framework, change the last line to this:

return objectContext.Products.AsExpandable().Where (predicate);

refer this for more details
http://neverindoubtnet.blogspot.com/2009/07/devforce-predicate-builder.html
http://drc.ideablade.com/xwiki/bin/view/Documentation/predicatebuilder-methods
  Irfan Khan replied to Arvind Subramani
27-Aug-11 04:06 AM

A predicate is a function that returns true or false for an item it evaluates. A query Where clause takes a predicate that filters items to include in the query result.

We need PredicateBuilder because combining predicates of either kind is hard in .NET. Let's illustrate with two predicate expressions.

C#
Expression<Func<Customer, bool>> expr1 = (Customer c) => c.CompanyName.StartsWith("A");
Expression<Func<Customer, bool>> expr2 = (Customer c) => c.CompanyName.Contains("e");
VB
Dim expr1 As Expression(Of Func(Of Customer, Boolean)) = _
  Function(c As Customer) c.CompanyName.StartsWith("A")
Dim expr2 As Expression(Of Func(Of Customer, Boolean)) = _
  Function(c As Customer) c.CompanyName.Contains("e")

It's easy to use either of these expressions independently; it's not obvious how to combine them.

C#
var query1 = myEntityManager.Customers.Where(expr1); // ok
var query2 = myEntityManager.Customers.Where(expr2); // ok
var queryBoth = myEntityManager.Customers.Where(expr1 && expr2) // BAD - won't compile.
VB
Dim query1 = myEntityManager.Customers.Where(expr1) ' ok
Dim query2 = myEntityManager.Customers.Where(expr2) ' ok
Dim queryBoth = myEntityManager.Customers.Where(expr1 AndAlso expr2) ' BAD - won't compile.

The PredicateBuilder can combine two predicates into a third predicate; then we pass that third predicate to the query's Where clause:

C#
var expr3 = PredicateBuilder.And(expr1, expr2);
var queryBoth = myEntityManager.Customers.Where(expr3); // this works
VB
Dim expr3 = PredicateBuilder.And(expr1, expr2)
Dim queryBoth = myEntityManager.Customers.Where(expr3) ' this works

Here's a more convenient syntax that uses PredicateBuilder's predicate expression extension methods to do the same thing without mentioning PredicateBuilder explicitly:

C#
var expr3 = expr1.And(expr2);
var queryBoth = myEntityManager.Customers.Where(expr3); // this works
VB
Dim expr3 = expr1.And(expr2)
Dim queryBoth = myEntityManager.Customers.Where(expr3) ' this works

http://drc.ideablade.com/xwiki/bin/view/Documentation/predicatebuilder-methods
http://social.msdn.microsoft.com/Forums/hu-HU/linqtosql/thread/dbb22f0b-4b51-443d-bdb8-ec0bc6182e94
http://www.codeproject.com/KB/linq/LINQDynamicPredicate.aspx
  James H replied to Arvind Subramani
27-Aug-11 08:56 AM

Dynamically Composing Expression Predicates

Suppose you want to write a LINQ to SQL or Entity Framework query that implements a keyword-style search. In other words, a query that returns rows whose description containssome or all of a given set of keywords.

We can proceed as follows:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  IQueryable<Product> query = dataContext.Products;

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    query = query.Where (p => p.Description.Contains (temp));
  }
  return query;
}

The temporary variable in the loop is required to avoid the outer variable trap, where the same variable is captured for each iteration of the foreachloop.

So far, so good. But this only handles the case where you want to match all of the specified keywords. Suppose instead, we wanted products whose description contains any of the supplied keywords. Our previous approach of chaining Where operators is completely useless! We could instead chain Union operators, but this would be inefficient. The ideal approach is to dynamically construct a lambda expression tree that performs an or-based predicate.

Of all the things that will drive you to manually constructing expression trees, the need for dynamic predicates is the most common in a typical business application. Fortunately, it’s possible to write a set of simple and reusable extension methods that radically simplify this task. This is the role of our PredicateBuilder class.

Using PredicateBuilder

Here's how to solve the preceding example with PredicateBuilder:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}

If querying with Entity Framework, change the last line to this:

return objectContext.Products.AsExpandable().Where (predicate);

The AsExpandable method is part of http://www.albahari.com/nutshell/linqkit.aspx (see below).

The easiest way to experiment with PredicateBuilder is with http://www.linqpad.net/. LINQPad lets you instantly test LINQ queries against a database or local collection and has direct support for PredicateBuilder (press F4 and check 'Include PredicateBuilder').

PredicateBuilder Source Code

Here's the complete source:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;
 
public static class PredicateBuilder
{
  public static Expression<Func<T, bool>> True<T> ()  { return f => true;  }
  public static Expression<Func<T, bool>> False<T> () { return f => false; }
 
  public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1,
                                                      Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters);
  }
 
  public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1,
                                                       Expression<Func<T, bool>> expr2)
  {
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ());
    return Expression.Lambda<Func<T, bool>>
          (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters);
  }
}

PredicateBuilder is also shipped as part of http://www.albahari.com/nutshell/linqkit.aspx, a productivity kit for LINQ to SQL and Entity Framework.

If you're using LINQ to SQL, you can use the PredicateBuilder source code on its own.

If you're using Entity Framework, you'll need the complete 
http://www.albahari.com/nutshell/linqkit.aspx - for the AsExpandable functionality. You can either reference LINQKit.dll or copy LINQKit's source code into your application.

How it Works

The True and False methods do nothing special: they are simply convenient shortcuts for creating an Expression<Func<T,bool>> that initially evaluates to true or false. So the following:

var predicate = PredicateBuilder.True <Product> ();

is just a shortcut for this:

Expression<Func<Product, bool>> predicate = c => true;

When you’re building a predicate by repeatedly stacking and/or conditions, it’s useful to have a starting point of either true or false (respectively). Our SearchProducts method still works if no keywords are supplied.

The interesting work takes place inside the And and Or methods. We start by invoking the second expression with the first expression’s parameters. An Invoke expression calls another lambda expression using the given expressions as arguments. We can create the conditional expression from the body of the first expression and the invoked version of the second. The final step is to wrap this in a new lambda expression.

Entity Framework's query processing pipeline cannot handle invocationexpressions, which is why you need to call AsExpandable on the first object in the query. By calling AsExpandable, you activate LINQKit's expression visitor class which substitutes invocation expressions with simpler constructs that Entity Framework can understand.

More Examples

A useful pattern in writing a data access layer is to create a reusable predicate library. Your queries, then, consist largely of select and orderby clauses, the filtering logic farmed out to your library. Here's a simple example:

public partial class Product
{
  public static Expression<Func<Product, bool>> IsSelling()
  {
    return p => !p.Discontinued && p.LastSale > DateTime.Now.AddDays (-30);
  }
}

We can extend this by adding a method that uses PredicateBuilder:

public partial class Product
{
  public static Expression<Func<Product, bool>> ContainsInDescription (
                                                params string[] keywords)
  {
    var predicate = PredicateBuilder.False<Product>();
    foreach (string keyword in keywords)
    {
      string temp = keyword;
      predicate = predicate.Or (p => p.Description.Contains (temp));
    }
    return predicate;
  }
}

This offers an excellent balance of simplicity and reusability, as well as separating business logic from expression plumbing logic. To retrieve all products whose description contains “BlackBerry” or “iPhone”, along with the Nokias and Ericssons that are selling, you would do this:

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                      .And (Product.IsSelling());
var query =
  from p in Data.Products.Where (newKids.Or (classics))
  select p;

The And and Or methods in boldface resolve to extension methods in PredicateBuilder
An expression predicate can perform the equivalent of an SQL subquery by referencing association properties. So, if 
Product had a child EntitySet called Purchases, we could refine our IsSelling method to return only those products that have sold a minimum number of units as follows:

public static Expression<Func<Product, bool>> IsSelling (int minPurchases)
{
  return prod =>
    !prod.Discontinued &&
     prod.Purchases.Where (purch => purch.Date > DateTime.Now.AddDays(-30))
                    .Count() >= minPurchases;
}

Nesting Predicates

Consider the following predicate:

p => p.Price > 100 &&
     p.Price < 1000 &&
     (p.Description.Contains ("foo") || p.Description.Contains ("far"))

Let's say we wanted to build this dynamically. The question is, how do we deal with the parenthesis around the two expressions in the last line?

The answer is to build the parenthesised expression first, and then consume it in the outer expression as follows:

var inner = PredicateBuilder.False<Product>();
inner = inner.Or (p => p.Description.Contains ("foo"));
inner = inner.Or (p => p.Description.Contains ("far"));

var outer = PredicateBuilder.True<Product>();
outer = outer.And (p => p.Price > 100);
outer = outer.And (p => p.Price < 1000);
outer = outer.And (inner);

Notice that with the inner expression, we start with PredicateBuilder.False (because we're using the Or operator). With the outer expression, however, we start with PredicateBuilder.True (because we're using the And operator).

Generic Predicates

Suppose every table in your database has ValidFrom and ValidTo columns as follows:

create table PriceList
(
   ID int not null primary key,
   Name nvarchar(50) not null,
   ValidFrom datetime,
   ValidTo datetime
)

To retrieve rows valid as of DateTime.Now (the most common case), you'd do this:

from p in PriceLists
where (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
      (p.ValidTo   == null || p.ValidTo   >= DateTime.Now)
select p.Name

Of course, that logic in bold is likely to be duplicated across multiple queries! No problem: let's define a method in the PriceList class that returns a reusable expression:

public static Expression<Func<PriceList, bool>> IsCurrent()
{
   return p => (p.ValidFrom == null || p.ValidFrom <= DateTime.Now) &&
               (p.ValidTo   == null || p.ValidTo   >= DateTime.Now);
}

OK: our query is now much simpler:

var currentPriceLists = db.PriceLists.Where (PriceList.IsCurrent());

And with PredicateBuilder's And and Or methods, we can easily introduce other conditions:

var currentPriceLists = db.PriceLists.Where (
                          PriceList.IsCurrent().And (p => p.Name.StartsWith ("A")));

But what about all the other tables that also have ValidFrom and ValidTo columns? We don't want to repeat our IsCurrent method for every table! Fortunately, we can generalize ourIsCurrent method with generics.

The first step is to define an interface:

public interface IValidFromTo
{
   DateTime? ValidFrom { get; }
   DateTime? ValidTo   { get; }
}

Now we can define a single generic IsCurrent method using that interface as a constraint:

public static Expression<Func<TEntity, bool>> IsCurrent<TEntity>()
   where TEntity : IValidFromTo
{
   return e => (e.ValidFrom == null || e.ValidFrom <= DateTime.Now) &&
               (e.ValidTo   == null || e.ValidTo   >= DateTime.Now);
}

The final step is to implement this interface in each class that supports ValidFrom andValidTo. If you're using Visual Studio or a tool like SqlMetal to generate your entity classes, do this in the non-generated half of the partial classes:

public partial class PriceList : IValidFromTo { }
public partial class Product   : IValidFromTo { }
Create New Account
help
entity framework .NET Framework Salve a tutti. Non riesco a istallare il entity framework su Visual Studio Team System 2008 Database Edition. Sapete dirmi se = E8 necessario qualche update? .NET Framework - Italian Discussions SQL Server 2005 (1) Entity Framework (1) Visual Studio (1) DotDotNet (1) Pack (1) Database (1) Sapete (1) Devi (1
Entity Framework .NET Framework Hola, Tengo instalado el Net Framework 3.5 SP1. Como puedo crear desde VisualStudio 2008 un Entity Framework? Gracias C# - Spanish Discussions Entity Framework (1) Visual Studio (1) VisualStudio (1) Necesitas (1) Gracias (1) Tengo (1) Hola (1) Plantilla
What i need in order to use Entity Framework .NET Framework Hi at all! I have Visual C# Express and Visual Web Developer Express installed, but i have found any reference in order to create Entity Framework Data Model. I need Visual Studio Standard / Professional edition in order to work with Entity Framework ? ck1; C# Discussions Visual
Umstieg LingToSQL -> Entity Framework .NET Framework , Entity, Framework" / > Hallo NG, meine Aufgabe wird es sein eine gr??ere .NET 3.5 WinForms-DB-Anwendung von LinqToSQL auf Entity Framework zu bringen, damit auch die Unterst?tzung f?r Oracle gegeben ist. So wie es ausschaut, werde ich schon mit der Beta von VS 2010 arbeiten, um die Erweiterungen des Entity-Frameworks nutzen zu k?nnen. W?re an dieser Stelle ?ber Literaturhinweise online / offline dankbar
Entity Framework samples files .NET Framework I am starting to get my feet wet on Entity Framework using sample files form MSDN. For some reason, when I go this link: http: / / msdn to downloading VS2008 SP1 download which I already have. Will appreciate any suggestions Thanks .NET Framework Discussions Entity Framework (1) ASP.NET (1) ADO.NET (1) VB.NET (1) LINQ (1) VB (1) Hi