Official BV Software Blog
New, Updates and Anything else we find interesting

How to create a Dynamic LINQ Query Programmatically

February 27, 2008 21:14 by mmcconnell1618

If you've been stuggling to create a dynamic LINQ query you're not alone. Thanks to some research, hard work and a smart co-worker I was able to implement some cool dynamic LINQ code in our help desk application. 

In our helpdesk we have filter screens that look like this: 



Creating a LINQ query in challenging because we don't know ahead of time which fields the user will complete. They are all optional and without anything selected we want to pull back all tickets. Normally, you'd write a query like this:

 

var ticket = (from t in db.cerberus_Tickets

                          where t.id == id

                          select t).Single();

In the example above we know that the t.id parameter will always be given. So how do you create a query in code when you don't know what fields to include in the WHERE clause ahead of time?

The first key is understanding the LINQ queries are not executed until they are used to enumerate through a collection. This part is key because it means we can create a query and change it in code as long as we don't try to look at the results first.

What we're going to do is create an IQueryable collection that contains all of our Ticket objects and we'll dynamically add our WHERE clause information.  Then we'll create a normal LINQ query that selects all of the matches from our IQueryable collection and handles paging. Because we don't actually enumerate the IQueryable collection that contains all our tickets, it won't actually pull back all of the tickets (which would take forever!). Instead, it will be "merged" with our normally LINQ query at run time when we enumerate over it.

1) Create our LINQ to SQL context objects

 

 

 List<cerberus_Ticket> result = new List<cerberus_Ticket>();

 cerberusDataContext db = new cerberusDataContext(connectionString);

 

2) Create an empty IQueryable collection containing all tickets. Note that this query doesn't actually select everything from the database yet. If it did this would take forever and effectively be filtering the database table in memory. That would not be a good design!

 

 

 IQueryable<cerberus_Ticket> matches = db.cerberus_Tickets;

 

3) Add our WHERE clause information with custom logic to decide if the clauses should be added or not

 

       

 if (this.AgentIdField.Text.Trim().Length > 0)

 {

     matches = matches.Where(a => a.AgentId == criteria.AgentId);

 }

 

 if (this.TicketIdField.Text.Trim().Length > 0)

 {

     matches = matches.Where(a => a.TicketId.Contains(criteria.TicketId));

 }

 

 4) Create a second LINQ query that selects from the first one to sort and page the results.

 

 // calculate start row based on page parameters passed in

 int startRow = (pageNumber - 1) * pageSize;

 

 var output = (from p in matches

               orderby p.DateCreated descending

               select p).Skip(startRow).Take(pageSize).ToList();

 

 

Again, I can't emphasize enough how cool it is that LINQ doesn't query the database until we call the ToList() at the end of the second statement. This delay in execution is the magic that lets us create dynamic queries on the fly.

Have any cool LINQ tips of your own to share?

 

 


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Quick program to batch rename files to replace text

February 23, 2008 14:42 by mmcconnell1618

Today I had a huge directory of 300+ images that I batch converted in Photoshop from TIFF to PNG format. The problem was I must have missed something in Photoshop and all the files came out like this:

 Image1.TIFF.PNG

I needed to remove the ".TIFF" part from the name so I wrote a quick c# command line program to look at a directory, find all files that contained text in their name and replace that with something else. It's a quick and dirty solution but I thought someone else might need it. The source directory, text to find and text to replace are just string in the source code. You may want to move them out to command line parameters if you need this kind of program often.

Here's the source code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.IO;

 

namespace FileNameChanger

{

    class Program

    {

        static void Main(string[] args)

        {

            /*

            * Change these three settings to tell the program

            * where to search, what to find and what to replace

            * it with

            */

            string sourceDir = @"C:\Users\mmcconnell\Desktop\CroppedTiff\PNG";

            string stringToFind = ".tiff.png";

            string stringToReplace = ".png";

 

            if (Directory.Exists(sourceDir))

            {

                string[] thefiles = Directory.GetFiles(sourceDir);

                if (thefiles != null)

                {

                    foreach (string f in thefiles)

                    {

                        string pathPart = Path.GetDirectoryName(f);

                        string filePart = Path.GetFileName(f);

                        filePart = filePart.Replace(stringToFind, stringToReplace);

                        File.Move(f, Path.Combine(pathPart, filePart));

 

                        Console.WriteLine("Moving to " + filePart);

                    }

                }

            }

        }

    }

}

 

 

 

Program.cs (1.26 kb)


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Visual Studio 2008 project in Visual Studio 2005

November 14, 2007 22:42 by mmcconnell1618

I've done a little research and it looks like PROJECT files are pretty much backwards compatible but SOLUTION files are not. While that's not as great as 100% compatible in most cases recreating the solution file is not a lot of work.

 


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

VS 2008 or Not?

November 14, 2007 21:05 by mmcconnell1618

Visual Studio 2008 is almost released into the wild. Microsoft has promised that it will be available by the end of this month. One of the great new features of VS2008 is the ability to compile projects that target .Net 2.0, 3.0 and 3.5. This is the first time since Visual Studio moved over to .Net that the toolset supports multiple frameworks.

There is a catch. Even though you can compile a 2.0 project with VS2008 you'll have to upgrade the project/solution files to the VS2008 format. That means if one person on your dev team moves to VS2008, the entire dev team for that project must be on VS2008. 

 When should BV move to VS2008? We'll have some people on the first day it's available asking why we're not shipping a VS2008 project. We'll have other people two years down the road complaining if we no longer support VS2005. Thoughts?

 

 


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5