Reusing Linq Queries

Today I was working on a class library(someone else wrote) that used Linq extensively. One of the problems I noticed was, there was no reuse of queries in the class. Every method pretty much return List<T> where T was a custom class that was created by joining three Linq to SQL tables. Here is an example of that.

image

Basically based on this schema, the developer was returning a custom class called Product Summary which would return data needed fields from all 3 tables. On this class there were quite a few methods and few of them were returning products based on category or supplier. Here is simple implementation of of these methods done by the existing developer.

image

Looking at the above code, you would notice the same problem that I saw when I first looked at the code. Both methods, GetProdByCat and GetProdBySupp has exactly the same implementation except for the filter they applied. So how could I reuse the query that class doesn't suffer from redundancy. Looking at the code the first time, I realized that he was returning a custom class called ProductSummary which was his own class not Linq table or a class generated by the ormapper so I felt that once you return a custom class, you further cannot apply transformation to it. But that surely is not true. Even when your select is returning a custom business class instead of Linq class, you can apply further transformations to it as long as your class returns an IQueryable<T>. Here is the class converted to reuse queries.

image

Looking at the above code, you will notice that class is much cleaner and its reusing queries because all the methods return IQueryable on which you can further apply transformation and filters.

Note: To those who think that both my methods GeProdByCat and GetProdBySup are applying filter in memory, this is certainly not the case. Any filter that you apply is being sent to the SQL server for execution.

8 Comments

  • I'm no Linq expert, but is it not the case that the original implementation would apply the filters in the SQL queries to the database?

    Whereas your modified version would return all rows, then apply the filter on the result.

    If this is true, then the original version may be potentially much more efficient.

  • Well it is not the case truly. That's what was amazing to me. Infact even though i am returning custsom object the entire query gets executed on sql server.

  • Thanks Zeeshan. Great article. This piece of information would help me in laying down the architecture of a new application I am developing in LINQ to Sql.

  • > Well it is not the case truly. That's what was amazing to me.
    Thanks for the clarification. It certainly does make it very powerful. I've read up a bit on IQueryable and see now that the expression tree that represents the query is not actually executed until the results of the query are enumerated.

  • Hi,

    Sounds good but is it possible to add an additional join statement that way?

  • @wuz:

    You can use an IQueryable in another linq query if you want. So I believe you could do something like:

    var r = from p in GetProdSumm() join t in SomeOtherTable on t.A equals p.B select p;

    And its all resolved as a SQL query.

  • I forgot to mention this only works in linq to sql not in entity framework.

  • too bad this only works for Linq2SQL and not for Linq2EF
    or is this possible since EF4?

Comments have been disabled for this content.