重视Linq技术_5

Building Query Expressions
//1、Compiling Expression Trees
Products.DeleteAllOnSubmit (Products.Where (p => p.ID == 999));
Products.InsertOnSubmit (new Product { ID = 999, Description = "Test", LastSale = DateTime.Now } );
SubmitChanges();
Product[] localProducts = Products.ToArray();
Expression<Func<Product, bool>> isSelling = 
	p => !p.Discontinued && p.LastSale > DateTime.Now.AddDays (-30);
IQueryable<Product> sqlQuery = Products.Where (isSelling);
IEnumerable<Product> localQuery = localProducts.Where (isSelling.Compile());

sqlQuery.Dump ("SQL Query");
localQuery.Dump ("Local Query, using same predicate");
//Compiling Expression Trees
Products.DeleteAllOnSubmit (Products.Where (p => p.ID == 999));
Products.InsertOnSubmit (new Product { ID = 999, Description = "Test", LastSale = DateTime.Now } );
SubmitChanges();

Product[] localProducts = Products.ToArray();

Expression<Func<Product, bool>> isSelling = 
	p => !p.Discontinued && p.LastSale > DateTime.Now.AddDays (-30);

IQueryable<Product> sqlQuery = Products.Where (isSelling);
IEnumerable<Product> localQuery = localProducts.Where (isSelling.Compile());

sqlQuery.Dump ("SQL Query");
localQuery.Dump ("Local Query, using same predicate");
//2、AsQueryable

 

void Main()
{
FilterSortProducts (Products).Dump ("This query executes on SQL Server");
Product[] localProducts =
{
new Product { ID = 1, Description = "Local Product Test", LastSale = new DateTime (2007, 2, 3) }
};
FilterSortProducts (localProducts.AsQueryable()).Dump ("The same query - executing locally");
}
IQueryable<Product> FilterSortProducts (IQueryable<Product> input)
{
return 
from p in input
where !p.Discontinued && p.LastSale < DateTime.Now.AddDays (-7)
orderby p.Description
select p;
}
//3、Examining an Expression Tree 
Expression<Func<string, bool>> f = s => s.Length < 5;

f.Body.NodeType.Dump ("Body.NodeType");
(((BinaryExpression) f.Body).Right).Dump ("Body.Right");

f.Dump ("The whole expression tree");

//4、Building an Expression Tree 
 
ParameterExpression p = Expression.Parameter (typeof (string), "s");
MemberExpression stringLength = Expression.Property (p, "Length");
ConstantExpression five = Expression.Constant (5);
BinaryExpression comparison = Expression.LessThan (stringLength, five);
Expression<Func<string, bool>> lambda = Expression.Lambda<Func<string, bool>> (comparison, p);
Func<string, bool> runnable = lambda.Compile();
runnable ("kangaroo")  .Dump ("kangaroo is less than 5 characters");
runnable ("dog")       .Dump ("dog is less than 5 characters");
//kangaroo is less than 5 characters
//False
//dog is less than 5 characters
//True
 
//5、Extra-Using PredicateBuilder 

 

string[] keywords = { "Widget", "Foo", "Bar" };
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or (p => p.Description.Contains (temp));
}
Products.Where(predicate).Dump("Notice the multiple OR clauses in the SQL pane");

//6、Extra - Dynamic Ordering Sample

IQueryable query =           // The original unordered query
from p in Purchases
where p.Price > 100
select p;

string propToOrderBy = "Price";    // Try changing this to "Description" or "Date"
ParameterExpression purchaseParam = Expression.Parameter (typeof (Purchase), "p");
MemberExpression member = Expression.PropertyOrField (purchaseParam, propToOrderBy);
LambdaExpression lambda = Expression.Lambda (member, purchaseParam);
Type[] exprArgTypes = { query.ElementType, lambda.Body.Type };
MethodCallExpression methodCall =
Expression.Call (typeof (Queryable), "OrderBy", exprArgTypes, query.Expression, lambda);
IQueryable orderedQuery = query.Provider.CreateQuery (methodCall);
orderedQuery.Dump();

//7、Extra - Dynamic Ordering Sample - How it Words

// Let's break down the last example. We started with a simple unordered query (remember
// that the query does not evaluate at this point, thanks to deferred execution):
IQueryable<Purchase> query =            // The original unordered query
from p in Purchases
where p.Price > 100
select p;
// Here's the property or field name upon which we want to order:
string propToOrderBy = "Price";    // Try changing this to "Description" or "Date"

// The aim is to dynamically constuct the following:
// var orderedQuery = query.OrderBy (p => p.Price);
// Starting from the inside out, we start by creating the lambda expression, p => p.Price.
// To dynamically build a LambaExpression, we first create the parameter, in this case, p.
// Our parameter is of type Purchase, and is called "p":
ParameterExpression purchaseParam = Expression.Parameter (typeof (Purchase), "p");
purchaseParam.Dump ("purchaseParam");

// Next, we need to create "p.Price". The static method Expression.PropertyOrField returns
// a MemberExpression that finds a property or field with the given name:

MemberExpression member = Expression.PropertyOrField (purchaseParam, propToOrderBy);
member.Dump ("member");

// With these two things, we build the LambdaExpression:
LambdaExpression lambda = Expression.Lambda (member, purchaseParam);
lambda.Dump ("lambda");
lambda.ToString().Dump ("lambda.ToString");

// We now need to wrap the lambda expression in a MethodCallExpression that
// references the Queryable.OrderBy method. For this, we call the static Expresion.Call
// method, which is overloaded especially to simplify the task of invoking methods
// that accept lambda expressions:

Type[] exprArgTypes = { query.ElementType, lambda.Body.Type };

MethodCallExpression methodCall =
Expression.Call (
typeof (Queryable),   // Type defining method we want to call
"OrderBy",                // Name of method to call
exprArgTypes,          // Generic argument types
query.Expression,     // First argument (the query expression body)
lambda);                // Second argument (the lambda expression)
methodCall.Dump ("methodCall (notice all the work that Expression.Call does for us)");

// The final step is to create the new query, which calls the expression we've just
//created. For this, we use the Provider property exposed by the IQueryable interface,
// which returns an object upon which we call CreateQuery:

IQueryable orderedQuery = query.Provider.CreateQuery (methodCall);
// (Exactly the same thing happens when you ordinarily call Queryable.OrderBy;
// a good way to see this is to download Lutz Roeder's Reflector at
// http://www.aisto.com/roeder/dotnet/ and look at Queryable's OrderBy method).
// Here's the final result:
orderedQuery.Expression.ToString().Dump ("The final result");

posted on 2012-03-04 23:47  Sanic  阅读(255)  评论(0编辑  收藏  举报

导航