Posts Tagged LINQ

Cool LINQ Stuff – queries and Reflection

This is something pretty cool that LINQ can be used for: querying information on Reflection data. For instance, the query below creates a list of all classes that are subclasses of the Exception class within the currently loaded assemblies. It also lists the properties declared at the subclasses level, making it easier to spot the properties that haven’t been inherited from the baseclass:

var exceptionClasses =
          from assembly in AppDomain.CurrentDomain.GetAssemblies()
          from type in assembly.GetTypes()
          where type.IsSubclassOf(typeof(Exception))
          from prop in type.GetProperties(BindingFlags.Instance | 
                                            BindingFlags.Public | 
                                            BindingFlags.DeclaredOnly)
          select new { AssemblyName = assembly.GetName().Name, 
TypeName = type.Name,
PropertyName = prop.Name }; foreach (var item in exceptionClasses) { Console.WriteLine(
String.Format("assembly = {0} | type = {1} | prop = {2}", item.AssemblyName, item.TypeName, item.PropertyName)); }

The query below gets all classes that implemented IEnumerable<T>, available on the currently loaded assemblies:

var query =
          from assembly in AppDomain.CurrentDomain.GetAssemblies()
          from type in assembly.GetTypes()
          from method in type.GetMethods()
          where method.IsStatic
          && method.ReturnType.GetInterface("IEnumerable`1") != null
          orderby method.DeclaringType.Name, method.Name
          group method by new
          {
                    Class = method.DeclaringType.Name,
                    Method = method.Name
          };

            foreach (var item in query)
            {
                Console.WriteLine(
                       item.Key.Class + " - " + item.Key.Method);
            }

 The last query I got from the following book (which is a great introduction to LINQ, by the way):

Introducing Microsoft LINQ
by Paolo Pialorsi, Marco Russo

Read more about this title…

Advertisements

Leave a comment

Cool LINQ stuff

LINQ is so cool. There’s just so much related to it that I feel like I don’t even know where dig deeper into it.

Coming from a Visual FoxPro background, I got pretty used to having a query language integrated right into the language. I also got pretty used to OOP, since VFP has OOP support since 1995. When I first got into .NET and noticed there wasn’t anything like VFP’s built-in query language, I thought "hmmm… this thing sucks!".

I was used to querying a backend to retrieve some data, and then query the in-memory data to do some filtering, sorting, etc, on the client side; all that was possible in VFP, but couldn’t really do it in .NET. The DataTable class has methods such as Select (that takes a "where-like" clause and returns an array of DataRows that match the criteria), and the Rows collection has a Find method (that takes a primay key and returns a reference to the row that matches the criteria). One can also play with DataViews to do some filtering and sorting (which I must confess I do like since it gives different views over the same set of data). But still, that all sucked when compared to doing a SELECT FieldA, FieldB FROM SomeInMemoryData WHERE Whatever = true GROUP BY Something ORDER BY SomethingElse right into the source code.

Enters LINQ!

One of the limitations of SQL as we know it in, say VFP or T-SQL, is that we query from rectangular data, and the outcome is another set of rectangular data. One cannot really create a result that’s a different "type":

RectToRect

One of the cool things about LINQ is that a query can go against any source that implements IEnumerable<T>, and the outcome can be really anything! For instance, one could query a collection of business entities, and the outcome could be a list of edit forms bound to the entities gathered by the query.

In other words, say my edit Form takes in an entity in its constructor, and uses that entity to bind it to UI controls… something simple like this:

    public partial class CustomerEditForm : Form
    {
        public CustomerEditForm(CustomerBusinessEntity entity)
        {
            InitializeComponent();

            this.textBox2.Text = entity.Name;
        }
    }

 Now say we have a collection of CustomerBusinessEntities like so:

var customers = new List<CustomerBusinessEntity>{
                new CustomerBusinessEntity("Claudio Lassala"),
                new CustomerBusinessEntity("John Jones"),
                new CustomerBusinessEntity("Cartman Smith")};

Say we want to write a query against that collection, looking for all Customers whose name starts with "C", and the outcome should be a collection of edit forms loaded with the entities gathered by the query. This is the code that does just that:

            var customerForms = 
                from customer in customers
                where customer.Name.StartsWith("C")
                select new CustomerEditForm(customer);

Now we can iterate through the query results and show the forms:

            foreach (var form in customerForms)
            {
                form.Show();
            }

 …and get the following result:

linqforms[1][1]

I think that is REALLY cool!

This sample uses the flavor of LINQ known as LINQ to Objects. There are other flavors of LINQ, such as LINQ to SQL (queries against SQL Server), LINQ to XML (queries against XML documents), etc. Those different flavors can be mixed, making it possible to implement some very interesting scenarios.

For instance, a query could select customers from a SQL database, join data from customers’  RSS feeds, join data from customers’  emails coming from Exchange server, do all sorts of filtering, grouping, sorting, etc., and the outcome could be, for instance, an XML document formatted to be consumed by some service that expects that format.

There’s a lot of great content regarding LINQ to SQL and LINQ to XML out there. For LINQ to SQL, make sure to check out Rick Strahl’s blog; he’s got a lot of great posts related to the topic, including some great stuff on how to create a business framework around LINQ to SQL to hide some of the plumbing from the developer. Also check out Scott Guthrie’s blog; he’s also got a lot of great tutorials on LINQ to SQL.

For LINQ to XML, check both Scott Hanselman’s blog (he’s got a bunch of posts about it), as well as this DNRTV episodes with DonXML.

There’s actually a lot of talk about LINQ to SQL and LINQ to XML, but I don’t hear a lot of talk about LINQ to Objects, and it seems to me the reason for that is because a lot of people haven’t quite figured out about this. I’ll continue posting what I considered cool queries that can be created with LINQ to Objects.

Leave a comment

DO’s and DON’Ts of LINQ

LINQ is such a powerful feature that developers are likely to use it everywhere in code, just like foreach blocks and if statement are. LINQ comes with different flavors of APIs, such as LINQ for Objects, LINQ for SQL, LINQ for XML, etc., each one of them being really powerful on what it does. Even though there are no restrictions as to where LINQ could be used, some of its APIs should be constricted to only be used in certain layers of code.

For example, LINQ for SQL should only be used by the Data Access Layer (DAL). The classes created to map objects to tables on the database (usually referred to as data context) should never be touched by any layer other than the DAL. Running a query from the UI against data contexts is like going directly to the database, which has never been a good idea.

LINQ for Objects, on the other hand, can (and should) be used everywhere. For instance, let’s say a given form has some logic that whenever a given condition is met, all the buttons on the form should be disabled. The traditional code for that would be a mix of foreach, typeof (or is), and if:  

foreach (Control control in this.Controls)
{ 
  if (control is Button) 
  { 
    control.Enabled = false; 
  }
}

The version with LINQ for Objects would look like so:  

var buttons = 
  from control in this.Controls.Cast<Control>().OfType<Button>() 
  select control;  

foreach (var button in buttons)
{ 
  button.Enabled = false;
}

The difference here isn’t that big because the only condition we’re looking for is to get every control of type Button within the form. The differences are more apparent in more complex scenarios.

Another example would be a case where we have a collection of entities representing customers, and we want to query that collection, and the outcome should be a collection of edit-forms editing the entities returned by the query. Like this:  

var customers = new List<CustomerBusinessEntity>{ 
                new CustomerBusinessEntity("Claudio Lassala"), 
                new CustomerBusinessEntity("John Jones"), 
                new CustomerBusinessEntity("Cartman Smith")}; 
 
var customerForms = 
  from customer in customers 
  where customer.Name.StartsWith(this.txtName.Text) 
  select new CustomerEditForm(customer); 

foreach
(var form in customerForms)

{ 
  form.Show();
}

The sky is the limit.

As I get a chance, I’ll probably be writing some custom FxCop rule to make sure I catch developers trying to run queries from the UI against data context (sort of like the one we currently have where we don’t allow developer to create IDbConnection objects directly, since all data access goes through our business objects).  

What was the Spiderman line: “With great power comes great responsibility”?  J

 

Leave a comment

LINQ: Can I have it now?? :)

It’s been awhile since I’ve seen LINQ for the first time. Back then, my reaction was: "Woah, this is awesome!! There’s only one problem with it: it’s not released yet…". That thing is one of those "I want it, and I want it now!!!".  🙂
 
There’s a new CTP for Orcas (the next version of Visual Studio), which brings the most recent version of LINQ, as well as great IDE enhancements for VS to work with LINQ. There’s a great post by Charlie Calvert where some good resources about LINQ are listed here:
 
I’m downloading the CTP right now to start playing with it.

Leave a comment