Using LINQ with ASP.NET (Part 1)

One of the new things I’m super excited about right now is the LINQ family of technologies that are starting to come out (LINQ, DLINQ, XLINQ and others soon).

 

LINQ will be fully integrated with the next release of Visual Studio (code-name: Orcas) and it will include some very cool framework and tool support (including full intellisense and designer support).  Last week the LINQ team released the May CTP drop of LINQ that you can download from here.  What is cool about this CTP is that it works with VS 2005, and allows you to start learning more about it immediately.  It incorporates a bunch of customer feedback (for example: support for stored procedures in DLINQ), and also includes a built-in ASP.NET Web-Site Project to enable you to leverage it with ASP.NET apps (note: you can also use LINQ with the new VS 2005 Web Application Project option as well).

 

I’m going to put together a few blog postings over the next few weeks that show off ways to use LINQ/DLINQ/XLINQ within ASP.NET projects.  This first walkthrough below will help you get started and introduce some of the important LINQ concepts.  You can follow-along by downloading the May CTP LINQ preview above and typing in the code below (I list all of it below), or you can download and run the complete .zip file of my samples here (note: you still need to install the LINQ May CTP drop for the .zip file of samples to work). 

 

Note: LINQ, DLINQ and XLINQ will be fully supported in both C# and VB.  I am using C# for the example belows.

 

Step 0: Creating a C# LINQ ASP.NET Web Site

 

To create a new ASP.NET Web Site that can use LINQ/DLINQ/XLINQ and the new C# 3.0 language features, choose File->New Web Site in VS and select the “LINQ ASP.NET Web Site Template”:

 

 

This will create a web-site project with the following files in-it by default:

 

 

Note that it includes a number of LINQ assemblies in the \bin folder.  It also adds the following setting to the app’s web.config file which tells both VS and ASP.NET to use the C# 3.0 compiler to compile and run the app:

 

    <system.codedom>

      <compilers>

        <compiler language="c#;cs;csharp"       

                  extension=".cs"

                  type="Microsoft.CSharp.CSharp3CodeProvider, CSharp3CodeDomProvider"/>

      </compilers>

    </system.codedom>

 

Note that the C# 3.0 compiler and CodeDOM provider can run side-by-side with the C# 2.0 versions (so you don’t have to worry about it breaking VS or ASP.NET when you install it). 

 

Step 1: Creating your first ASP.NET page using LINQ

 

Create a new page called Step1.aspx.  Within the .aspx page add a GridView control like so:

 

<%@ Page Language="C#" CodeFile="Step1.aspx.cs" Inherits="Step1" %>

 

<html>

<body>

    <form id="form1" runat="server">

    <div>

   

        <h1>City Names</h1>

   

        <asp:GridView ID="GridView1" runat="server">

        </asp:GridView>

   

    </div>

    </form>

</body>

</html>

 

Within the code-behind file we’ll then write the canonical “hello world” LINQ sample – which involves searching and ordering a list of strings:


using System;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Query;

 

public partial class Step1 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        string[] cities = { "London", "Amsterdam", "San Francisco", "Las Vegas",

                            "Boston", "Raleigh", "Chicago", "Charlestown",

                            "Helsinki", "Nice", "Dublin" };

 

        GridView1.DataSource = from city in cities

                               where city.Length > 4

                               orderby city

                               select city.ToUpper();

 

        GridView1.DataBind();

    }

}

 

In the above sample I’ve created an array of strings listing the cities I’ve visited from Jan->May of this year.   I’m then using a LINQ query expression against the array.  This query expression returns all cities where the city name is greater than 4 characters, and orders the result in alphabetical order and transforms those city names into upper case.

 

LINQ queries return results of type: IEnumerable<T> -- where <T> is determined by the object type of the “select” clause.  In the above sample “city” is a string, so the type-safe result is a generics based collection like so:

 

        IEnumerable<string> result = from city in cities

                                     where city.Length > 4

                                     orderby city

                                     select city.ToUpper();

 

Because ASP.NET controls already support databinding to any IEnumerable collection, we can easily assign this LINQ query result to the GridView and call its DataBind() method to generate this page output result:

 

 

Note that instead of using the GridView control I could have just as easily used the <asp:repeater>, <asp:datalist>, <asp:dropdownlist>, or any other ASP.NET list control (both those built-into the product or ones built by other developers).  For the purposes of these samples I’m just going to use the <asp:gridview> -- but again know that you can use any. 

 

Step2: Using Richer Collections

 

Searching an array of strings is not terribly interesting (although sometimes actually useful).  More interesting would be the ability to search and work against richer collections of our own making.  The good news is that LINQ makes this easy.  For example, to better track trips I can create a simple class called “Location” in my project below:

 

using System;

 

public class Location

{

    // Fields

    private string _country;

    private int    _distance;

    private string _city;

 

    // Properties

    public string Country

    {

        get { return _country; }

        set { _country = value; }

    }

 

    public int Distance

    {

        get { return _distance; }

        set { _distance = value; }

    }

 

    public string City

    {

        get { return _city; }

        set { _city = value; }

    }

}

 

This exposes 3 public properties to track the County, City name and Distance from Seattle.  I can then create a Step2.aspx file with a GridView control that defines 3 columns like so:

 

<%@ Page Language="C#" CodeFile="Step2.aspx.cs" Inherits="Step2" %>

 

<html>

<body>

    <form id="form1" runat="server">

 

    <h1>Cities and their Distances</h1>

   

    <asp:GridView ID="GridView1" AutoGenerateColumns="false" runat="server">

       <Columns>

          <asp:BoundField HeaderText="Country" DataField="Country" />

          <asp:BoundField HeaderText="City" DataField="City" />

          <asp:BoundField HeaderText="Distance from Seattle" DataField="Distance" />

       </Columns>

    </asp:GridView>

   

    </form>

</body>

</html>

 

I can then populate a collection of Location objects and databind it to the Grid in my code-behind like so:

 

using System;

using System.Collections.Generic;

using System.Web;

using System.Query;

 

public partial class Step2 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        List<Location> cities = new List<Location>{

                                    new Location { City="London", Distance=4789, Country="UK" },

                                    new Location { City="Amsterdam", Distance=4869, Country="Netherlands" },

                                    new Location { City="San Francisco", Distance=684, Country="USA" },

                                    new Location { City="Las Vegas", Distance=872, Country="USA" },

                                    new Location { City="Boston", Distance=2488, Country="USA" },

                                    new Location { City="Raleigh", Distance=2363, Country="USA" },

                                    new Location { City="Chicago", Distance=1733, Country="USA" },

                                    new Location { City="Charleston", Distance=2421, Country="USA" },

                                    new Location { City="Helsinki", Distance=4771, Country="Finland" },

                                    new Location { City="Nice", Distance=5428, Country="France" },

                                    new Location { City="Dublin", Distance=4527, Country="Ireland" }

                                };

 

        GridView1.DataSource = from location in cities

                               where location.Distance > 1000

                               orderby location.Country, location.City

                               select location;

 

        GridView1.DataBind();

    }

}

 

The above code-behind shows off a few cool features.  The first is the new C# 3.0 support for creating class instances, and then using a terser syntax for setting properties on them: 

 

new Location { City="London", Distance=4789, Country="UK" }

 

This is very useful when instantiating and adding classes within a collection like above (or within an anonymous type like we’ll see later).  Note that rather than use an array this time, I am using a Generics based List collection of type “Location”.  LINQ supports executing queries against any IEnumerable<T> collection, so can be used against any Generics or non-Generics based object collections you already have. 

 

For my LINQ query I’m then returning a collection of all cities that are more than 1000 miles away from Seattle.  I’ve chosen to order the result in alphabetical order – first by country and then by city name.  The result of this LINQ query is again dictated by the type of the “location” variable – so in this case of type “Location”:

 

        IEumerable<Location> result = from location in cities

                                      where location.Distance > 1000

                                      orderby location.Country, location.City

                                      select location;

 

When I databind this result against the GridView I get a result like so:

 

 

Step 3: Refactoring the City Collection Slightly

 

Since we’ll be re-using this collection of cities in several other samples, I decided to encapsulate my travels in a “TravelOrganizer” class like so:

 

using System;

using System.Collections.Generic;

 

public class TravelOrganizer

{

    public List<Location> PlacesVisited

    {

        get

        {

            List<Location> cities = new List<Location>{

                                        new Location { City="London", Distance=4789, Country="UK" },

                                        new Location { City="Amsterdam", Distance=4869, Country="Netherlands" },

                                        new Location { City="San Francisco", Distance=684, Country="USA" },

                                        new Location { City="Las Vegas", Distance=872, Country="USA" },

                                        new Location { City="Boston", Distance=2488, Country="USA" },

                                        new Location { City="Raleigh", Distance=2363, Country="USA" },

                                        new Location { City="Chicago", Distance=1733, Country="USA" },

                                        new Location { City="Charleston", Distance=2421, Country="USA" },

                                        new Location { City="Helsinki", Distance=4771, Country="Finland" },

                                        new Location { City="Nice", Distance=5428, Country="France" },

                                        new Location { City="Dublin", Distance=4527, Country="Ireland" }

                                    };

 

            return cities;

        }

    }

}

 

This allows me to then just write the below code in our code-behind to get the same result as before:

 

using System;

using System.Collections.Generic;

using System.Web;

using System.Web.UI;

using System.Query;

 

public partial class Step3 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        TravelOrganizer travel = new TravelOrganizer();

 

        GridView1.DataSource = from location in travel.PlacesVisited

                               where location.Distance > 1000

                               orderby location.Country, location.City

                               select location;

 

        GridView1.DataBind();

    }

}

 

What is really cool about LINQ is that it is strongly-typed.  What this means is that:

 

1) You get compile-time checking of all queries.  Unlike SQL statements today (where you typically only find out at runtime if something is wrong), this means you will be able to check during development that your code is correct (for example: if I wrote “distanse” instead of “distance” above the compiler would catch it for me).

 

2) You will get intellisense within VS (and the free Visual Web Developer) when writing LINQ queries.  This makes both typing faster, but also make it much easier to work against both simple and complex collection and datasource object models.

 

Step 4: Skipping and Taking using .NET Standard Query Operators

 

LINQ comes with built-in support for many built-in Standard Query Operators.  These can be used within code by adding a “using System.Query” statement at the top of a class file, and can be applied to any sequence of data.   For example, if I wanted to list cities in order of distance and list the 2nd->6th farthest away cities I could write my code-behind file like so:

 

using System;

using System.Web.UI;

using System.Query;

 

public partial class Step4 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        TravelOrganizer travel = new TravelOrganizer();

 

        GridView1.DataSource = (from location in travel.PlacesVisited

                               orderby location.Distance descending

                               select location).Skip(1).Take(5);

 

        GridView1.DataBind();

    }

}

 

Note how I am ordering the result by the distance (farthest to least).  I am then using the “Skip” operator to skip over the first city, and the "Take" operator to only return the remaining 5. 

 

What is really powerful is that the .NET Standard Query Operators are not a hard-coded list, and can be added to and replaced by any developer.  This enables very powerful domain specific implementations.  For example, when the Skip() and Take() operators are used with DLINQ – it translates the calls into back-end SQL logic that performs server-side paging (so that only a few rows are returned from the SQL database – regardless of whether it is from a table with 100,000+ rows of data).  This means that you will be able to trivially build efficient web data paging over lots of relational data (note: until then you can use the techniques listed here). 

 

Step 5: More Fun with .NET Standard Query Operators

 

In addition to returning sequences of data, we can use .NET Standard Query Operators to return single or computed results of data.  The below samples show examples of how to-do this:

 

<%@ Page Language="C#" CodeFile="Step5.aspx.cs" Inherits="Step5" %>

 

<html>

<body>

    <form id="form1" runat="server">

    <div>

        <h1>Aggregate Value Samples</h1>

       

        <div>

            <b>Farthest Distance City:</b>

            <asp:Label ID="MaxCityNameTxt" runat="server" Text="Label"></asp:Label>

            <asp:Label ID="MaxCityDistanceTxt" runat="server" Text="Label"></asp:Label>

        </div>

       

        <div>

            <b>Total Travel Distance (outside of US):</b>

            <asp:Label ID="TotalDistanceTxt" runat="server" Text="Label"></asp:Label>

        </div>       

       

        <div>

            <b>Average Distance:</b>

            <asp:Label ID="AverageDistanceTxt" runat="server" Text="Label"></asp:Label>

        </div>       

       

    </div>

    </form>

</body>

</html>

 

Step5.aspx.cs code-behind file:

 

using System;

using System.Collections.Generic;

using System.Web.UI;

using System.Query;

 

public partial class Step5 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        TravelOrganizer travel = new TravelOrganizer();

 

 

        //

        // Calculate farthest city away

 

        Location farthestCity = (from location in travel.PlacesVisited

                                 orderby location.Distance descending

                                 select location).First();

 

        MaxCityNameTxt.Text = farthestCity.City;

        MaxCityDistanceTxt.Text = "(" + farthestCity.Distance + " miles)";

 

 

        //

        // Calculate total city distances of all cities outside US

 

        int totalDistance = (from location in travel.PlacesVisited

                             where location.Country != "USA"

                             select location).Sum(loc => loc.Distance);

 

        TotalDistanceTxt.Text = totalDistance + " miles";

 

 

        //

        // Calculate average city distances of each city trip

 

        double averageDistance = travel.PlacesVisited.Average(loc => loc.Distance);

 

        AverageDistanceTxt.Text = averageDistance + " miles";

    }

}

 

Note that the last two examples above use the new Lambda Expression support – which enable fragments of code (like delegates) that can operate on top of data to compute a result.  You can build your own .NET Query Operators that use these (for example: you could build domain specific ones to calculate shipping costs or payroll tax).  Everything is strongly-typed, and will support intellisense and compilation checking support.

 

The output of the above sample looks like so:

 

 

Step 6: Anonymous Types

 

One of the new C# and VB language features that LINQ can take advantage of is support for “Anonymous Types”.  This allows you to easily create and use type structures inline without having to formally declare their object model (instead it can be inferred by the initialization of the data).  This is very useful to “custom shape” data with LINQ queries. 

 

For example, consider a scenario where you are working against a database or strongly-typed collection that has many properties – but you only really care about a few of them.  Rather than create and work against the full type, it might be useful to only return those properties that you need.  To see this in action we’ll create a step6.aspx file like so:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Step6.aspx.cs" Inherits="Step6" %>

 

<html>

<body>

    <form id="form1" runat="server">

    <div>

       

        <h1>Anonymous Type</h1>

   

        <asp:GridView ID="GridView1" runat="server">

        </asp:GridView>

       

    </div>

    </form>

</body>

</html>

 

And within our code-behind file we’ll write a LINQ query that uses anonymous types like so:

 

using System;

using System.Web.UI;

using System.Query;

 

public partial class Step6 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        TravelOrganizer travel = new TravelOrganizer();

 

        GridView1.DataSource = from location in travel.PlacesVisited

                               orderby location.City

                               select new {

                                    City = location.City,

                                    Distance = location.Distance

                               };

          

        GridView1.DataBind();

    }

}

 

Note that instead of returning a “location” from our select clause like before, I am instead creating a new anonymous type that has two properties – “City” and “Distance”.  The types of these properties are automatically calculated based on the value of their initial assignment (in this case a string and an int), and when databound to the GridView produce an output like so:

 

 

Step 7: Anonymous Types (again)

 

The previous sample showed a basic example of using anonymous types to custom-shape the output of a LINQ query.  The below sample provides a richer and more practical scenario.  It transforms our list of cities into a hierarchical result collection – where we group the results around countries using an anonymous type that we define that contains the country name, a sub-collection list of city details, and the sum of the total distance of all cities within the country (computed using a lambda expression like we demonstrated in step5 above):

 

using System;

using System.Web.UI;

using System.Query;

 

public partial class Step7 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        TravelOrganizer travel = new TravelOrganizer();

 

        GridView1.DataSource = from location in travel.PlacesVisited

                               group location by location.Country into loc

                               select new {

                                   Country = loc.Key,

                                   Cities = loc,

                                   TotalDistance = loc.Sum(dist => dist.Distance)

                               };

          

        GridView1.DataBind();

    }

}

 

The GridView on our .aspx page is then defined like so:

 

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Step7.aspx.cs" Inherits="Step7" %>

 

<html>

<body>

    <form id="form1" runat="server">

    <div>

        <h1>Groupings with Anonymous Classes</h1>

 

        <asp:GridView ID="GridView1" AutoGenerateColumns="false" runat="server">

            <Columns>

           

                <asp:BoundField HeaderText="Country" DataField="Country" />

           

                <asp:TemplateField HeaderText="Cities">

                    <ItemTemplate>

                   

                        <asp:BulletedList ID="BulletedList1" runat="server"

                                          DataSource='<%#Eval("Cities")%>' DataValueField="City"/>

                   

                    </ItemTemplate>

                </asp:TemplateField>

           

                <asp:BoundField HeaderText="Total Distance" DataField="TotalDistance" />

           

            </Columns>

        </asp:GridView>

    </div>

    </form>

</body>

</html>

 

Notice how I’ve added a GridView templatefield column for the “Cities” column – and within that I’ve then added an <asp:bulletedlist> control (a new control built-in with ASP.NET 2.0) that databinds its values from the cities property of the hierarchical result we created using our LINQ query above.  This generates output like so:

 

 

Note that all of the databind syntax and hierarchical binding support in the .aspx page above is fully supported in ASP.NET 2.0 today – so you can use this same technique with any existing app you have now.  What is new (and I think very cool) is the data shaping capabilities provided by anonymous types and LINQ – which makes binding hierarchical data against ASP.NET controls very easy.

 

Next Steps

 

All of my samples above were against in-memory collections.  They show you how you will be able to use LINQ against any .NET object model (includes all the ones you have already).

 

In my next few LINQ-related blog postings I’ll show how you can go even further, and take advantage of the new DLINQ support to use the above techniques against relational databases as well as the new XLINQ support to work against XML files and structures.  What is great about the LINQ project is that the syntax and concepts are the same across all of its uses – so once you learn how to use LINQ against an array or collection, you also know all the concepts needed to work against a database or even XML file.

 

For example, if you use DLINQ to generate a Northwinds database mapping of Suppliers and their Products (no code is required to set this up), the below code is all you need to write to obtain and databind a hierarchical database result against a GridView like we did above (note: we are using the same data-shaping technique as our previous sample to only require fetching two columns from the database, and automatically join the products of each supplier as a hierarchical group result):

 

using System;

using System.Query;

 

public partial class Data_Data2 : System.Web.UI.Page

{

    protected void Page_Load(object sender, EventArgs e)

    {

        Northwind db = new Northwind();

 

        GridView1.DataSource = from x in db.Suppliers

                               where x.Country == "USA"

                               orderby x.Country

                               select new {

                                    x.CompanyName,

                                    x.Country,

                                    x.Products

                               };

 

        GridView1.DataBind();

    }

}

 

No custom SQL syntax or code is required – this is all that needs to be written to efficiently fetch and populate hierarchical data now (note: only the rows and columns needed will be fetched -- DLINQ can use the remote function support within LINQ so that it does not need to materialize or fetch the full database table or all columns from a row).  And it is all type-safe, with full compiler checking, intellisense, and debugging supported.

 

Even better, the ability to plug-in new LINQ providers (of which DLINQ and XLINQ are just two examples) is completely open – so developers who either build or use existing data providers today (for example: O/R database mappers) can easily integrate their implementations with LINQ to have a seamless developer experience.  Once you know LINQ you will know all the basics needed to program against any of them.

 

Summary

 

Hopefully this provides a glimpse of some of the cool new things coming.  You can try it all out today by downloading the May CTP drop of LINQ today from here.  You can also download and run all of the samples I built above from this .ZIP file here.

 

Hope this helps,

 

Scott

61 Comments

  • Excellent! Thanks for the update Scott. I can't wait to start trying this stuff out. Keep up the good work.

  • Hi Scott,



    Great article, thanks.



    Just one question:



    select location).Skip(1).Take(5);



    Why do you skip number 1 and not number 0 ?

    If I'm right, you are selected lines and s, it should start at 0.





    Can you give me more details ?



    Thank you very much :)





    Bye





    Thomas LEBRUN

  • Any ideas about the release date of Orcas?

  • Hi Igor,



    My guess is that you haven't installed the May CTP LINQ drop. Can you confirm that you have had?



    Also -- have you added a &quot;using System.Query&quot; statement to the top of the class where you are using the LINQ syntax? The error could be coming from that.



    Hope this helps,



    Scott



    P.S. Lastly -- if the above two suggestions don't work, please try running the sample using the built-in VS web-server to see if that makes a difference (it shouldn't -- but maybe it does).

  • Hi Tom,



    Skip() takes the number of results to skip in the sequence (and not the row to start with). I provided &quot;1&quot; as the argument so that it would skip over the first result.



    Hope this helps,



    Scott

  • Hi Paketim,



    We are looking to ship the second half of next year. We will start having full Orcas CTP drops (of all technologies) starting later this summer, and will also have a go-live license of Orcas before the final RTM date. So not too far off now when you can use the above techniques in production.



    Hope this helps,



    Scott

  • Scott,



    This DLINQ stuff looks very promising for providing a long awaited MS O/R Mapper. However, i have got excited by new datahandling functionality being introduced in the past only to find that the are usually many reasons why it can't be used in an enterprise n-tier project.



    When you provide DLINQ examples do you think you would be able to go that extra mile and show how it would be used in an n-tier application that may use business logic to validate, augment and/or transform the data before it gets written to the database?



    Many Thanks

  • Hi Scott,



    I wonder if VWD support it?

  • Hi Scott,



    I installed it on my VS 2005 team edition RTM 050727-4200, I got a lot of problems:

    1. After I type using System., I can not see Query.

    2. After I type GridView1., I can not see anything :-(, all the controls got this problem.



    can you help me?

    thanks in advance.

  • Pleased you stated your C# examples are in C# 3.0. I the tried example from &quot;Step2: Using Richer Collections&quot; in VWD Express and there was a complaint on syntax.



    I had to do this:



    List&lt;Location&gt; cities = new List&lt;Location&gt;

    Location loc = new Location(&quot;Uk&quot;, 5000, &quot;London&quot;);

    cities.Add(loc);



    to make it work.

  • Scott Guthrie is using FireFox :)

  • List&lt;Location&gt; cities = new List&lt;Location&gt;{

    new Location { City=&quot;London&quot;, Distance=4789, Country=&quot;UK&quot; },

    new Location { City=&quot;Amsterdam&quot;, Distance=4869, Country=&quot;Netherlands&quot; }

    }



    Of course, when doing all this within your ASPX page, you could also define this as an anonymous type avoiding the need to define the type at all:

    var cities = new[] {

    new { City=&quot;London&quot;, Distance=4789, Country=&quot;UK&quot; },

    new { City=&quot;Amsterdam&quot;, Distance=4869, Country=&quot;Netherlands&quot; }

    }



    And your code will work great. Of course, when you move this to a separate PlacesVisited class, it is more difficult because you cannot return an anonymous type. However you could still do this and just return type Object (provided you perform your query within the method), as ASP.NET will still correctly will databind against it using reflection.



    And I am sure eventually Orcas will include a standard refactor to extract the type!



    Nice stuff isnt it!



    David Taylor

  • Hi Jason,



    Sure -- I will try and add some samples to the DLINQ tutorials to show that. You can provide both property and entity validation with DLINQ.



    Note that LINQ itself is decoupled from DLINQ and XLINQ. That way if you prefer to use a different data implementation or O/R mapper you can. Our expectation is that existing enterprise data providers will move to support LINQ against them relatively quickly after Orcas ships to give developers even more flexibility to choose from.



    Hope this helps,



    Scott

  • Windows PowerShell (Monad).



    Scott, if you have not yet had a chance, I encourage you to look at Windows PowerShell. I completely ignored it at the 2005 PDC, but finally took a look after RC1 came out a few weeks ago.



    The funny thing is I have spent lots of time since the PDC thinking about LINQ, and now that I look at PowerShell I see the same concepts.



    A few weeks ago I didnt know what a Monad Comprehension was (actually I still dont...).



    But with PowerShell you can do stuff like:



    dir | sort Length | select Name, Length



    Which in LINQ syntax would be:

    from dir in Directory.GetFiles(&quot;.&quot;)

    order dir by dir.Length

    select new {Name, Length};



    Very cool stuff.

  • Hi VC,



    VWD will definitely support it with the final release. I think you can make the May CTP work with VWD today (even though it says you need VS) - although I haven't tried myself (I don't have a machine that only has VWD installed).



    Hope this helps,



    Scott

  • Hi VC,



    The language services support for C# 3.0 don't support intellisense that well yet, which is why you won't get full intellisense in your pages when you use LINQ statements (this applies both to the LINQ statements and other controls on the page). Obviously this will be fully supported by VS in the future though.



    Compilation error messages are accurate and correct though -- so even if you don't get intellisense you will get compile error checking with the May CTP.



    Hope this helps,



    Scott

  • Hi DOM,



    The syntax I used was for the C# 3.0 compiler to create the collection -- if you had to write code like you did above then I suspect the issue is that you still have the C# 2.0 compiler mapped to your project (which doesn't support those constructs yet).



    Hope this helps,



    Scott

  • Nice sample David! :-)



    One other trick you might have noticed is that you can assign a anonymous instance to a variable defined using the &quot;var&quot; keyword.



    For example:



    var foo = (some anonymous instantiation);



    You can then program against the anonymous type in a strongly typed way (you'll even get intellisense in VS Orcas with it).



    Hope this helps,



    Scott

  • Hi Paul,



    Yep -- you can use all of this with Atlas. :-)



    The nice thing about Lambdas is that they provide a way you can write functions that are passed as arguments for later evaluation. This is useful for a lot of data scenarios (especially filtering and calculations), and the Lamdbda syntax is much terser than what you'd need to otherwise write today. They are also fully type-safe for compile-time and intellisense support.



    Hope this helps,



    Scott

  • I was wondering whether Orcas is going to ship with a new major CLR and Framework version, or whether it will be built on top of the 2.0 framework.



    I'm particularly wondering because I feel strongly that anonymous types ought to have CLR-level support so that it's possible, at a language level, to provide a syntax for referring to them explicitly and have equivalent anonymous types remain equivalent across assemblies.



    My preferred syntax in C# would be something like this:



    var x = {Name=&quot;Me&quot;, Age=10};

    @{string Name, int Age} y = x;



    So far, though, what information I've seen about Orcas has been almost entirely innovation at the language and library levels, with virtually no CLR support whatsoever. I hope that the feeling within MS isn't that the CLR is &quot;done&quot; and mature and not a space for further innovation, because there are other future features that I think are important that would need be added at a CLR level also.

  • Hi Stuart,



    We are definitely adding new Framework libraries in Orcas. We are making some changes to the CLR for that release, but are also being careful to keep a high runtime compat bar to ease deployments (the following release will then have more engine additions).



    Note that you can do something similar to the syntax you mentioned above today:



    var x = new {Name=&quot;Me&quot;, Age=10};

    var y = x;



    What isn't as convenient is cross assembly passing of this variable. Obviously you can do it as type &quot;Object&quot; -- but given that it is anonymous you can't then cast it in a type-safe way. I'll follow up with some folks to discuss whether there might be a nice syntax for doing this.



    Thanks,



    Scott

  • Thanks for the clarification, I'm glad that even if Orcas is being conservative there's still room for CLR features in the future. I'd hate for 2.0 to be the last really innovative CLR release ;)



    The problem with passing as Object cross-assembly isn't a purely syntactical one (back before Cyrus dropped off the face of the earth I had some discussions with him about syntax for this so I know it's been on the C# team's radar at some point) but the fact that even if two assemblies contain identical anonymous types, those types are completely different at the runtime level because the runtime doesn't have any capability to express the concept of a type defined structurally outside the scope of a particular assembly. So even if a given language *wanted* to add a syntax which would let you cast to an anonymous type, it's simply not possible right now in cross-assembly calls, because the cast would always fail.

  • Hi Scott,



    Will Orcas be a new version of the .NET Framework (3.0) or will it be compatible with 2.0 as it is now?



    Regards,

    Mikael S&#246;derstr&#246;m

  • Scott,



    Another obvious question. Is it possible using the LINQ CTP and ASP.NET to completely pre-compile a website such that you can deploy it on a machine without without the LINQ CTP installed?



    For example, with the earlier LINQ CTP, I wrote a class library that used LINQ but from a method just returned a string as XML. Then from an ASP.NET app I bound against the XML (using the XmlDataSource and XPath). Nice thing was that this worked *perfectly* even thought the machine I ran it on did *not* have LINQ installed - it ran just fine with all the LINQ assemblied copied into the ASP.NET bin directory (including my class library that contained the only reference to LINQ).



    So my question: If you directly use LINQ from within an ASP.NET page (or code behind page), and you pre-compile the entire site, would it be possible to deploy on a machine without LINQ installed and just the correct assemblies copied into the bin directory?



    Also....You really really really should check out PowerShell if you like LINQ. PowerShell and LINQ are conceptually identical. PowerShell has a nicer, shorter syntax than LINQ for common scenarios (command line usage, etc) - while LINQ is more general. But learning usage of either technology will help you with the other :-)

  • LINQ looks pretty sweet. One thing tho, when I try to enable paging on the GridView I get &quot;The data source does not support server-side data paging.&quot;.

  • Will it be possible to use LINQ to do queries with the generic ODBC driver?

  • it looks really cool. but i wonder how robust it is, and how scalable it is when the data collection increases in size.



    does LINQ offers any kinds of data indexing like database? like indexing an object field in a collection, like how database index a table column?? just curious.

  • Hi Mikael,



    Orcas will be compatible with the 2.0 runtime. There will then be optional framework components you can install as well.



    Hope this helps,



    Scott

  • Hi David,



    You should be able to compile an app using LINQ and then deploy it on a vanilla ASP.NET 2.0 machine (providing you copy the LINQ assemblies to the \bin directory).



    In fact, if you use the VS 2005 Web Application Project this will work perfectly for you.



    Hope this helps,



    Scott



    P.S. I will definitely check out PowerShell -- thanks for the pointer!

  • Hi CN,



    I will show how to enable paging with the GridView in a future tutorial. The simplest way to make it work is to use the ObjectDataSource and return LINQ results from it.



    Hope this helps,



    Scott

  • Hi George,



    You can do LINQ queries against any collection or object model. DLINQ will then have a pluggable provider API -- so someone could connect it to any data source. The built-in provider in the May CTP is for SQL, but others could build an ODBC one.



    Hope this helps,



    Scott

  • Hi Netism,



    LINQ works against any object model, and is as efficient as writing code against it today.



    DLINQ works against databases, and provides a way to use LINQ queries to perform data operations. The SQL it generates on the wire is pretty good (I will blog about that in the future). One nice thing about DLINQ is that you also always have the ability to escape it and provide custom SQL if you want.



    Hope this helps,



    Scott

  • Great article. I'm looking forward to using C# in 3.0!

  • I tried to deploy this application onto my hosting and unfortunately, it seems to need &quot;full trust&quot; permission which my hosting does't allow of it. &nbsp;Not sure if it's because it needs linq installed or if it's because my hosting.



    I will try to deploy this onto another machine and see.

  • Hi Liming,

    Unfortunately the May CTP does require full trust permissions to run. The final release, though, will support medium trust.

    Hope this helps,

    Scott

  • I tried doing a query using the DataContext, but my class with a table attribute of &quot;Production.Product&quot; didn't work, saying it was an invalid entity. I had a valid connectionstring, pointing to the AdventureWorks database.

  • Great article...



    Going to try this out as soon as find some time for it!



    Thanks

  • Hi Jonas,

    Have you tried posting this to the LINQ/DLINQ forums? They might be the best people to help with this.

    Thanks,

    Scott

  • Scott, When you give examples please make them relevant to real world scenarios.

    In what way is a business application going to benefit in using this rather than passing a sql statement or calling a stored proc.



    What are the advantages of this technology?



    Why is Microsoft spending money on reinventing the wheel?

  • Hi Scott, I am new to .NET and have little experiemce .. I wanted to ask you a question(hope its not stupid..) What is the Use of Linq , DLinq etc is there any link for that.. Thanks

  • Hi MT,

    I just posted part 2 of this series here: http://weblogs.asp.net/scottgu/archive/2006/06/04/Using-DLINQ-with-ASP.NET-_2800_Part-2-of-my-LINQ-series_2900_.aspx

    It goes into more depth on some of the cool data scenarios that LINQ enables.

    Hope this helps,

    Scott

  • Hi, Simple and wonderful article. I have few questions. Other than arrays and datasets, what other objects could be used along with Linq queries? Does it work with all collection types? regards bala

  • Hi Bala,

    Yep -- LINQ will work against any array or custom collection type. Basically it can perform queries against any sequence or collection that implements IEnumerable.

    Hope this helps,

    Scott

  • We just tried it out on our new architecture, it works, pretty funky stuff really.

  • Good Stuff, Scott!!!. Simple and Short...

    Keeps me enumerating...

    I had downloaded a two part asp.net WMV of yours from Channel 9...Nice Ones...

    Cheers

    --Subbu

  • simple and powerful application.

    easy data access from array. very interesting

  • Scoot

    When I new project ,I can't find dlinq project template, my installation is May CTP build.

    How can I enable it

    thanks

    xm

  • Hi Scott,

    Do you know if it's possible to run LinQ against a custom object model? I have an object model that's pretty complex but it does implement IEnumerable. However, I can't figure out a way to run LinQ except by generated a LinQ object model, which seems like it's generating unneccesary code as I already have one. I could be missing something completely obvious, hopefully someone smarter than I can point me in the right direction :)

  • Hi Jason,

    Yep -- you can definitely run LINQ over a custom object model just fine. As long as it support IEnumerable you can perform queries without having to modify your object model (which is pretty cool).

    Hope this helps,

    Scott

  • I am not sure if I understood LINQ and the advantage of introducing this technology. Instead of writing the pre compilied stored procedures in database we are are trying to embed LINQ query ( which will generate SQL) inside the .net code. Isnt it a messy thing to embed linq Code into business or UI tier?
    Is it that one should write the linq query in DAL and create a method there to retrieve the collection of objects from DAL?

  • Hai,

    I am new in LINQ.I dont know much more about LINQ.But work out samples which you given above really its supper.I want know whats actual purpose of LINQ and advantages compare to SQl statement.

    Regards

    Ranjith.M

  • Hi Ranjith,

    The big advantages of LINQ over using SQL statements directly are:

    1) It is a cleaner, terser syntax
    2) It is checked by the compiler instead of at runtime
    3) It can be easily debugged
    4) It can be used against any datatype - it isn't limited to relational databases, you can also use it against XML, regular objects, etc.

    Hope this helps,

    Scott

  • Hi John,

    LINQ is very fast and uses pretty proven object relational mapping concepts, so I wouldn't say it is a research project.

    LINQ is not released yet, but will be next year. It will be fully supported and tested, and designed for both large and small systems.

    Hope this helps,

    Scott

  • Thanks for answers Scott. But those are only words. Are there any proves? Like client testimonials? Why don't you have the same approach as when testing mssql with chosen clients and getting their feedback before release? Any technology related to data manipulation is extremely important and sensitive so why not do it as in case of mssql? Or do you have some pilot projects you could present us and that would be a prove of your words? I would be really happpy Scott to see it! Really!
    And I've not got the answer regarding var. Why do you push this? We want to stay with clasic approach, we strongly dislike this pseudo-strongly typed system (it's like vb6 where you would get the same results as in this case and we all know what problems it caused). So we would be happy to turn this option off for a compiler. Would it be possible? It's just our freedom of choise to decide isnt it?a

  • Hi Scott,

    Just hit LINQ, DLINQ and Polita's excellent BLINQ... Excellent, been waiting for it a long time. Used BLINQ to whip up and admin site for a new db protoype, lots of brownie points!

    Any idea when the next release will be? I've seen posts saying second half next year, but to be honest, writing all my data access with NHibernate and then switching to LINQ will be a bummer, I'd prefer to go straight to LINQ as soon as possible.

    I've compiled the BLINQ project with astnet_compiler, so it can deploy on a 2.0 only machine, but I'd prefer to have a Go-Live, CTP isn't cutting it with my boss :(

    Once again, thanks for the intro.

    Kev

  • Hi Kevin,

    Unfortunately it is going to be early next year when we get LINQ ready for the next major release (which will be the productized version that is fully integrated into Visual Studio).

    I know it is really addictive (I love it). We'll try and get it out to you as soon as possible though.

    Thanks,

    Scott

  • Hi Scott, caught your presentation at NDDNUG...thanks, it was great! Immediately started playing with LINQ and BLINQ. I pointed BLINQ at our main application and it generated a DataContext of around 100,000 lines of code. I also played with LINQ briefly to manually try and separate the DataContext out into smaller classes. What's your recommendation for larger databases where it doesn't seem realistic to use one DataContext? I've worked on some fairly large databases with 1000+ tables. Thanks again for coming to NDDNUG!

  • Hi Jimbo,

    That is a good scenario!

    Can you send me email (scottgu@microsoft.com) and I'll loop you in with a few folks from the LINQ team to discuss? They'd probably have some good recommendations for you.

    Thanks,

    Scott

  • great article....thanxxx

  • I have Microsoft .net linq preview (May 2006) installed and tried "Step 1: Creating your first ASP.NET page using LINQ", but the linq statement is unrecognized, "city", "in", "cities", and "ToUpper()" are all red underlined with "; expected"

    from city in cities
    where city.Length > 4
    orderby city
    select city.ToUpper();

  • Thanks.. :)
    Excellent article for LINQ

Comments have been disabled for this content.