Lambda Expressions and Stored Procedures - c#

I'm trying to mimic the LINQ Where extension method for my ADO.NET DAL methods.
Bascially, my aim is to have a single method that I can call. Such as:
Product p = Dal.GetProduct(x => x.ProductId == 32);
Product p2 = Dal.GetProduct(x => x.ProductName.Contains("Soap"));
I then want to dissect those Predicates and send the filter options to parameters in an ADO.NET Stored Procedure call.
Any comments greatly appreciated.

As #Daniel points out, this is far from simple. The solution outline is to let GetProduct take an argument of type Expression<Func<Product, bool>>. You then have to traverse the parse-tree of this expression, generating the correct SQL for functions known and also decide how to handle unknown functions. There are basically two options for that:
Throw an error (as linq-to-sql does).
Skip it in the translation and then apply it on the returned result. The performance impact of this can of course be huge if a lot of data is retreived just to be filtered out.
It would be a fun exercise to do it - but I can hardly see a way to justify it in the real world, when there are already linq2sql, linq2entities and linq2NHibernate that does the job.

In addition to Anders's answer, I just want to mention that you can analyze the expression tree by using an expression visitor. To do that, you can inherit the ExpressionVisitor class (it's new in .NET 4, but you can find a 3.5 implementation in LinqKit) and override the methods you want to analyze each node.
You might also be interested in those links :
Building a LINQ Provider
Walkthrough: Creating an IQueryable LINQ Provider

Related

Can a linq query EVER change its data source, i.e. a dictionary's content?

It seems to me that Linq can only -query- a given data source, that is, it browses through it and returns stuff from it as necessary, but doesn't change anything. However, the wording in some of the answers I found on the matter are making me doubt this understanding. Is my understanding correct in all circumstances? Can a linq query -ever- change the content of the data source it is associated to?
Can a linq query -ever- change the content of the data source it is associated to?
Yes, though this is a bad idea.
LINQ queries (at least with LINQ to Objects) work by using delegates for the filter or mapping operations. In general, these shouldn't ever cause side effects, but that doesn't mean that they couldn't do so if you forced them to. The actual LINQ methods won't change the data, but they work via delegates that are just code you provide, which means that code could do anything.
Note that this would, in general, be a bad idea.
For example, say you were doing a query over a collection of Person instances:
var results = people.Where(p => p.Name == "Foo")
.Select(p =>
{
// This is evil, don't do it!
p.Name = "Bar";
return p;
});
That being said, this is unlikely to work with LINQ against an IQueryable<T>. In that case, the lambda you provide will be converted into an Expression, which will in turn need to be translated by the provider into some other form (ie: Entity Framework converts this to SQL). As such, you would only be able to create side effects if the provider was written in a way that this would translate into a meaningful form, which is unlikely to be the case.

Overloading .Where extension with IQueryable<T> implementation

My question is how / when it makes sense to overload (if thats possible?) the Where() extension method of IQueryable when you are making your own IQueryable implementation?
For example in Entity Framework its my understanding that a Where() call made against an ObjectSet will change the actual SQL thats being passed to the database. Alternatively if you cast to IEnumerable() first the filtering is done with LINQ-To-Objects rather than LINQ-To-Entities.
For instance:
new MyDBEntities().MyDbTable.Where(x => x.SomeProperty == "SomeValue");
// this is linq-to-entities and changes the database-level SQL
Versus:
new MyDBEntities().MyDbTable.AsEnumerable().Where(x => x.SomeProperty == "SomeValue");
// this is linq-to-objects and filters the IEnumerable
How do you deal with this when implementing your own IQueryable and IQueryable already has pre-defined extension methods such as Where()? Specifically I want make my own very simple ORM that uses native SQL and SqlDataReader under the hood, and want to have a .Where() method that changes the native SQL before passing it to the database.
Should I even use IQueryable or just create my own class entirely? I want to be able to use lambda syntax and have my SQL command altered based on the lambda function(s) used for filtration.
You could create your own type analogous to IQueryable<T>, but that's probably not a good idea. You should probably write your own implementation of the interface. There is a nice series of articles on how to do it, but be prepared, doing so is not one of the easier tasks.

Best approach to dynamically filter .Net objects

The project I'm working currently on has a way to define a filter on objects from a database.
This filter is a pretty straightforward class containing criteria that will be combined to produce a SQL where clause.
The goal now is to use this class to filter .Net objects as well. So for example the filter might specify that the title property of the object that it is applied to must contain some user-defined string.
What are ways to approach this problem? What should the filter return instead of the sql where-clause and how can it be applied to the object? I've been think about this for hours and don´t yet have even a slight idea how to solve this. Been thinking about reflection, dynamic code execution, building expressions but still haven´t found a starting point.
It depends on what all the use-cases are :)
If your DB code could use LINQ, then I might consider returning an Expression<Func<YourEntity,bool>>, as this can be applied via .Where to both DB-based LINQ and LINQ-to-Objects - in the latter case simply by calling:
var filtered = original.AsQueryable().Where(filter);
(DB code is typically already queryable, so no AsQueryable is needed).
One bad thing about this is that there is no guarantee that a particular query expression will work on every LINQ provider.
Alternatively, you would have to write either your own basic query language, or a basic tree-structure. And then write code to translate to both property-reflection and SQL. Lots of work.
One final thought is to just have two different query results, and keep the two thigs separate. So one SQL, one Predicate<T> or similar. There is a risk of them being out of sync, though.
If you want to do it a bit like the dynamically created SQL where clause, you could use Dynamic LINQ to achieve similar effects.

I want to be able to use a lambda expression to specify a range of values to return over a wcf service

I have no idea if this is possible ... but it would be cool. the question is whether it is possible but then a bit of an example if possible.
I am not sure what method signature you would use to pass the lambda expression into.
Eg the method IList<Group> GetGroups()
How would you modify that to be able to pass a lambda expression into it?
The next question is how would you code a lambda expression to return all Group objects where for example
where .deleted == false or
where .DateAdded > aDate
Yeah, I want the moon on a stick ;)
Thanks in advance.
(edit I am thinking this is a bit ill-conceived actually because of the data access layer that would actually fetch the data ... but assume that you are querying some object collection over the service and don't have to worry about the dal).
You could declare the GetGroups method with a parameter of type Expression<Func<Group, bool>>, which represents a predicate that the group must match in order to be returned :
IList<Group> GetGroups(Expression<Func<Group, bool>> predicateExpression);
The trouble is, expressions can't be serialized, so you couldn't send it to the WCF service... However, you might find a way to do it with the Expression Tree Serialization project.
You could
define a simple query language that your back-end service understands
the web service exposes a method that takes a string in this query language
write a client-side conversion system that takes in an IQueryable full of expression trees, and translates that into the query language
now the client can either write queries in your query language directly, or can write LINQ queries which your translator turns into your query language
hey, you just invent LINQ-To-Tortoise!
Matt Warren has seventeen blog articles about how to do this sort of thing.
I think that RIA services do what you want, but I do not know the magic behind it.
You could pass a "predicate": A Func<Group, bool>, which returns true or false for a given Group. Since you can pass a lambda where a Func is expected, this could be something like:
var fooGroups = GetGroups(g => g.Name.StartsWith("Foo"));

What are some instances in which expression trees are useful?

I completely understand the concept of expression trees, but I am having a hard time trying to find situations in which they are useful. Is there a specific instance in which expression trees can be applied? Or is it only useful as a transport mechanism for code? I feel like I am missing something here. Thanks!
Some unit test mocking frameworks make use of expression trees in order to set up strongly typed expectations/verifications. Ie:
myMock.Verify(m => m.SomeMethod(someObject)); // tells moq to verify that the method
// SomeMethod was called with
// someObject as the argument
Here, the expression is never actually executed, but the expression itself holds the interesting information. The alternative without expression trees would be
myMock.Verify("SomeMethod", someObject) // we've lost the strong typing
Or is it only useful as a transport mechanism for code?
It's useful as an execution mechanism for code. Using the interpreter pattern, expression trees can directly be interpreted. This is useful because it's very easy and fast to implement. Such interpreters are ubiquitous and used even in cases that don't seem to “interpret” anything, e.g. for printing nested structures.
Expression trees are useful when you need to access function logic in order to alter or reapply it in some way.
Linq to SQL is a good example:
//a linq to sql statement
var recs (
from rec in LinqDataContext.Table
where rec.IntField > 5
select rec );
If we didn't have expression trees this statement would have to return all the records, and then apply the C# where logic to each.
With expression trees that where rec.IntField > 5 can be parsed into SQL:
--SQL statment executed
select *
from [table]
where [table].[IntField] > 5

Categories