SingingEels : Development Community & Resource

Login

Articles

  • ADO.NET (2)
  • ASP.NET (29)
  • LINQ (4)
  • Security (2)
  • Silverlight (2)
  • SQL (7)
  • Standards (5)
  • WCF (1)

Syndication

  • Articles RSS
  • Blogs RSS

Contribute

  • Our Authors List
  • Member Sign-Up
  • Suggestions Box

LINQ to SQL is My Hero!

(Mar 05 2008 - 04:26:41 PM by Timothy Khouri) - [print blog post]

I've been using LINQ for a while now (LINQ to Objects, and LINQ to SQL mainly) and I just saw something absolutely beautiful that I've never seen before. First, though, I'll give you a little history on the problem that I had (and everyone else in the world who uses Microsoft SQL Server will at some point run into).

Now, don't get me wrong, I love Microsoft SQL Server (2005 in particular), and I know that it is absolutely the best database out there... but there is one task in particular that comes up often, but is difficult to do.

The Scenario

Imagine if you had a website dedicated to top quality development articles (much like this one), and you wanted to display a "related blogs" section on your site. This would allow users to see blog posts that are similar to the article they are reading. Sounds simple enough, and it is... the only problem is that your articles can belong to multiple categories!

If you don't see the problem yet, then it's probably because you haven't run into it. So I'll show you by an example here why my simple desire won't work. If articles could only belong to one category, then your "get related blog posts" SQL code would look something like this:

SELECT
   *
FROM
   dbo.BlogPosts
WHERE
   Category = @SelectedCategory

But, we want to be able to search multiple categories... So, we need to do something like this:

SELECT
   *
FROM
   dbo.BlogPosts
WHERE
   Category = @SelectedCategoryA
       OR Category = @SelectedCategoryB

The problem here is that there can be any number of selected categories... so unless you want to dynamically build a SQL string, your out of luck. Also, if you made a stored procedure to house your code, there's little you can do (that isn't a nasty hack) to get the job done.

LINQ to SQL Builds Dynamic Queries

So, to get to the good stuff, what I realized is that LINQ to SQL does the nasty deed of building a SQL string for you. So, here is my LINQ code (in C#):

// I'm hardcoding these categories as an example... but the point
// is that they can be selected by a user dynamically.

string[] selectedCategories = new string[] { "ASP.NET", "LINQ", "WCF" }

var blogPosts = from blogPost in context.BlogPosts
   where selectedCategories.Contains(blogPost.CategoryName)
   select blogPost;

And here is the SQL code that will be built on the fly by LINQ:

-- This is not an exact example here, but I'm basically "roughing" it.
SELECT * FROM dbo.BlogPosts WHERE CategoryName IN (@p0, @p1, @p2)

You guessed it; LINQ to SQL is parameterizing the categories and using an "IN" statement... beautiful!

Conclusion

If you have no idea what I'm talking about above, it's probably because you're not familiar with LINQ or SQL... but all I can say is, you should really start getting into .NET 3.5 and LINQ. Hopefully I can finish up this re-write soon and start getting back to development articles.

  • Mar 05 2008 - 05:39:13 PM TaiZ

    If the number of the parameters is unkown, here is a solution I implemented with SQL Server 2000:

    (using your example)

    declare @Categories varchar(2000)

    set @Categories = 'ASP.NET, LINQ, WCF'

    SELECT * FROM dbo.BlogPosts WHERE CategoryName IN(

    Select [Value] from dbo.StringToTable(@Categories)

    )

    where dbo.StringToTable is a user-defined function that splits a string into a single-column table

    I haven't started using .NET 3.5 and LINQ, but I mean that problem is solvable with SQL.

    Regards,

    TaiZ

  • Mar 06 2008 - 06:40:01 AM Timothy Khouri

    Hey TaiZ,

    That's one of the cleanest solutions out there, and I've done something similar in the past. Another approach is using a LIKE statement similar to what you're doing (that way you don't have to make the UDF, not that it's a bad thing).

    Here's what I used to do:

    DECLARE @Categories VARCHAR(8000)

    SELECT @Categories = '|ASP.NET|LINQ|WCF|'

    SELECT * FROM dbo.BlogPosts WHERE @Categories LIKE '%|' + CategoryName + '|%'

    The only problem with this solution (and yours above) is that you have to make sure that you know that the data doesn't have pipes ( | ) or in your case commas ( , )... but that's not an issue in this example.

    Great comment by the way!

  • Mar 11 2008 - 10:12:45 PM Rod McBride

    Timothy, I have ran into the issue you just described many times and have found a nice way to address it using the CHARINDEX function in SQL Server. In addition, CHARINDEX was a lot faster than using the "IN" clause, especially if a sub-select was use.

    As a result, you can simply revised the query like this:

    SELECT *

    FROM dbo.BlogPosts

    WHERE CHARINDEX(CategoryName, 'ASP.NET, LINQ, WCF') > 0

    The delimited list of category names can also be built dynamically if needed or simply passed in to a stored procedure as a parameter value. Here is a minor change to use a variable for the category names.

    DECLARE @categories VARCHAR(64)

    SET @categories = 'ASP.NET, LINQ, WCF'

    SELECT * FROM dbo.BlogPosts WHERE CHARINDEX(CategoryName, @categories) > 0

    Thanks for the info on LINQ. I just started using it and really like what I have seen so far.

You must be logged in to add comments. If you have not already done so, you can create an account here. If you already are a member, you first need to login before you can comment.

Developer / Architect / Author

People to Follow

Experts in the categories related to this blog post.

  • Jonathan Carter

Related Blogs

These are the most recent blog posts related to this blog post.

  • My Bad Coding Habits, Thanks LINQ to SQL!
  • Dynamic LINQ OrderBy using String Names!
  • Silverlight Beta Has WCF, LINQ, Windows Controls!
  • LINQ to SQL is My Hero!

Related Ads

SingingEels.com as of Jul 23 2008 - 12:10:20 PM - (0.0625028)