Professional ASP.NET 3.5 in C# and Visual Basic Part 52 ppsx

10 407 0
Professional ASP.NET 3.5 in C# and Visual Basic Part 52 ppsx

Đang tải... (xem toàn văn)

Thông tin tài liệu

Evjen c09.tex V2 - 01/28/2008 2:09pm Page 466 Chapter 9: Querying with LINQ Next, the code uses a very simple LINQ query to select all of the Movie objects from the generic movies collection. Notice that this specific LINQ query utilizes new language keywords like from and select in the query statement. These syntax additions are first class members of the .NET languages, therefore Visual Studio 2008 can offer you development assistance such as strong type checking and IntelliSense, making it easier for you to find and fix problems in your code. The query also defines a new variable m . This variable is used in two ways in the query. First, by defining it in the from statement from m , we are telling LINQ to make m represent the individual collection item, whichinthiscaseisa Movie object. Telling LINQ this enables it to understand the structure of the objects we are querying, and as you will see later, also gives us IntelliSense to help create the query. The second use of m in the query is in the select statement. Using m in the select statement tells LINQ to output a projection that matches the structure of m . In this case that means LINQ creates a projection that matches the Movie object structure. We could just have easily created our own custom projection by explicitly defining the fields we wanted returned from the query using the new keyword along with the select operator. This is shown below in Listing 9-7. Listing 9-7: Creating a c ustom projection with LINQ VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Select New With {m.Title, m.Genre} Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var query = from m in movies select new { m.Title, m.Genre }; this.GridView1.DataSource = query; this.GridView1.DataBind(); } Notice that rather than simply selecting m , we have defined a new projection containing only the Title and Genre values. You can even go so far as to explicitly define the field names that the objects in the resultset will expose. For example, you may want to more explicitly name the Title and Genre fields to more fully describe their contents. Using LINQ, it’s easy to do this, as shown in Listing 9-8. 466 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 467 Chapter 9: Querying with LINQ Listing 9-8: Creating custom projection field names VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Select New With {.MovieTitle = m.Title, .MovieGenre = m.Genre} Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var query = from m in movies select new { MovieTitle = m.Title, MovieGenre = m. Genre }; this.GridView1.DataSource = query; this.GridView1.DataBind(); } This sample explicitly defined the Fields that will be exposed by the resultset as MovieTitle and MovieGenre. You can see in Figure 9-1, that because of this change, the column headers in the GridView have changed to match. Figure 9-1 Customized GridView column headers as the result of the LINQ projection 467 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 468 Chapter 9: Querying with LINQ Finally the code binds the GridView control to the enumerable list of Movie object returned by the LINQ query. As shown in Figure 9-2, running the code from Listing 9-6 results in the same vanilla Web page as the one generated by Listing 9-2. Figure 9-2 The results of a basic LINQ query bound to a GridView control LINQ also includes the ability to order the results using the order by statement. As with SQL you can choose to order the results in either ascending or descending order, as shown in Listing 9-9. Listing 9-9: Controlling data ordering using LINQ VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Order By m.Title Descending _ Select New With {.MovieTitle = m.Title, .MovieGenre = m.Genre} Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); 468 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 469 Chapter 9: Querying with LINQ var query = from m in movies orderby m.Title descending select new { MovieTitle = m.Title, MovieGenre = m. Genre }; this.GridView1.DataSource = query; this.GridView1.DataBind(); } Another great feature of the new LINQ syntax is the dramatic improvement in readability and under- standability that it makes in your code. LINQ enables you to simply express the intention of your query, indicating to the compiler what you want your code to do, but leaving it up to the compiler to best determine how it should be done. While these new keywords are what enable you to construct LINQ queries using a simple and clear SQL-like syntax, rest assured there is no magic occurring. These keywords actually map to extension methods on the Movies collection. You could actually write the same LINQ query directly using these extension methods and it would look like this: VB Dim query = movies.Select( Function(m as Movie) m ) C# var query = movies.Select(m => m); This is what the compiler translates the keyword syntax into during its compilation process. You may be wondering how the Select method got added to our generic List < Movies > collection because if you look at the object structure of List < T >, there is no Select method. LINQ adds the Select method, and many other methods it uses to the base Enumerable class, using Extension Methods. Therefore, any class that implements IEnumerable will be extended by LINQ with these methods. You can see all of the methods added by LINQ by right-clicking on the Select method in Visual Studio and choosing the View Definition option from the context menu. Doing this causes Visual Studio to display the class metadata for LINQ’s Enumerable class. If you scroll through this class, you will see not only Select ,butother methods such as Where , Count , Min , Max , and many other methods that LINQ automatically adds to any object that implements the IEnumerable interface. Delayed Execution An interesting feature of LINQ is its delayed execution behavior. This means that even though you may execute the query statements at a specific point in your code, LINQ is smart enough to delay the actual execution of the query until it is accessed. For example, in the previous samples, although the LINQ query was written before the binding of the GridView controls, LINQ will not actually execute the query we have defined until the GridView control begins to enumerate through the query results. Query Filters LINQ also supports adding query filters using a familiar SQL-like where syntax. You can modify the LINQ query from Listing 9-3 to add filtering capabilities by adding a where clause to the query, as shown in Listing 9-10. 469 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 470 Chapter 9: Querying with LINQ Listing 9-10: Adding a filter to a LINQ query VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Where m.Genre = 0 _ Select m Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var query = from m in movies where m.Genre==0 select m; this.GridView1.DataSource = query; this.GridView1.DataBind(); } By adding this simple where clause to the LINQ query, the results returned by the query are filtered to show movies from the 0 genre only, as shown in Figure 9-3. Figure 9-3 A filtered list of Movies Also, notice that, because LINQ is a first-class member of .NET, Visual Studio is able to provide an excellent coding experience as you are constructing your LINQ queries. In this sample, as you enter the 470 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 471 Chapter 9: Querying with LINQ where clause, Visual Studio gives you IntelliSense for the possible parameters of m (the Movie object), as shown in Figure 9-4. Figure 9-4 Because LINQ is a first class language concept, Visual Studio can give you Intellisense The where clause in LINQ behaves similarly to the SQL where clause, enabling you to include sub-queries and multiple where clauses, as shown in Listing 9-11. Listing 9-11: Adding a Where clause to a LINQ query VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Where m.Genre = 0 And m.Runtime > 92 _ Select m Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var query = from m in movies where m.Genre == 0 && m.RunTime > 92 select m; this.GridView1.DataSource = query; this.GridView1.DataBind(); } In this sample, the where clause includes two parameters, one restricting the movie genre, the other restricting the movie’s runtime. 471 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 472 Chapter 9: Querying with LINQ Data Grouping LINQ also greatly simplifies grouping data, again using a SQL-like group syntax. To show how easy LINQ makes this, you can modify the original Listing 9-4 to use a LINQ query. The modified code is shown in Listing 9-12. Listing 9-12: Grouping data using a LINQ query VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim query = From m In movies _ Group By m.Genre Into g = Group, Count() Me.GridView1.DataSource = query Me.GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var query = from m in movies group m by m.Genre into g select new { Genre = g.Key, Count = g.Count() }; this.GridView1.DataSource = query; this.GridView1.DataBind(); } This LINQ query uses the group keyword to group the movie data by genre. Additionally, because a group action does not naturally result in any output, the query creates a custom query projection using the techniques discussed earlier. The results of this query are shown in Figure 9-5. Figure 9-5 Grouped data results 472 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 473 Chapter 9: Querying with LINQ Using LINQ to do this allows you to significantly reduce the lines of code required. If we compare the amount of code required to perform the grouping action in Listing 9-4, with the previous listing using LINQ, you can see that the number of lines of code has dropped from 18 to 3, and the readability and clarity of the code has improved. Other LINQ Operators Besides basic selection, filtering and grouping, LINQ also includes many operators you can execute on enumerable objects. Most of these operators are available for you to use and are similar to operators you find in SQL, such as Count, Min, Max, Average, and Sum, as shown in Listing 9-13. Listing 9-13: Using LINQ query operators VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Me.TotalMovies.Text = movies.Count.ToString() Me.LongestRuntime.Text = movies.Max(Function(m) m.Runtime).ToString() Me.ShortestRuntime.Text = movies.Min(Function(m) m.Runtime).ToString() Me.AverageRuntime.Text = movies.Average(Function(m) m.Runtime).ToString() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); this.TotalMovies.Text = movies.Count.ToString(); this.LongestRuntime.Text = movies.Max(m => m.RunTime).ToString(); this.ShortestRuntime.Text = movies.Min(m => m.RunTime).ToString(); this.AverageRuntime.Text = movies.Average(m => m.RunTime).ToString(); } This listing demonstrates the use of the Count, Max, Min, and Average operators with the movies collec- tion. Notice that for all but the Count operator, you need to provide the method with the specific field you want to execute the operation on. This is done using a Lambda expression. LINQ Joins LINQ also supports the unioning of data from different collections using a familiar SQL-like join syntax. For example, in our sample data thus far, we have only been able to display the Genre as a numeric ID. It would be preferable to actually display the name of each Genre instead. To do this, you simply create a Genre class, which defines the properties of the genre, as shown in Listing 9-14 Listing 9-14: A simple Genre class VB Public Class Genre Private _id As Integer Private _name As String Continued 473 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 474 Chapter 9: Querying with LINQ Public Property ID() As Integer Get Return _id End Get Set(ByVal value As Integer) _id = value End Set End Property Public Property Name() As String Get Return _name End Get Set(ByVal value As String) _name = value End Set End Property End Class C# public class Genre { public int ID { get; set; } public string Name { get; set; } } Next you can add a GetGenres method to your Web page that returns a list of Genre objects, as shown in Listing 9-15. Listing 9-15: Populating a collection of Genres VB Public Function GetGenres() As List(Of Genre) Dim genres As Genre() = { _ New Genre With {.ID = 0, .Name = "Comedy"}, _ New Genre With {.ID = 1, .Name = "Drama"}, _ New Genre With {.ID = 2, .Name = "Action"} _ } Return New List(Of Genre)(genres) End Function C# public List<Genre> GetGenres() { return new List<Genre> { new Genre { ID=0, Name="Comedy" } , new Genre { ID=1, Name="Drama" } , new Genre { ID=2, Name="Action" } }; } 474 Evjen c09.tex V2 - 01/28/2008 2:09pm Page 475 Chapter 9: Querying with LINQ Finally, you can modify the Page Load event, including the LINQ query, to retrieve the Genres list and, using LINQ, join that to the Movies list. This is shown in Listing 9-16. Listing 9-16: Joining Genre data with Movie data using a LINQ query VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim genres = GetGenres() Dim query = From m In movies Join g In genres _ On m.Genre Equals g.ID _ Select New With {.Title = m.Title, .Genre = g.Name} GridView1.DataSource = query GridView1.DataBind() End Sub C# protected void Page_Load(object sender, EventArgs e) { var movies = GetMovies(); var genres = GetGenres(); var query = from m in movies join g in genres on m.Genre equals g.ID select new { m.Title, Genre = g.Name } ; this.GridView1.DataSource = query; this.GridView1.DataBind(); } As you can see in this sample, the join syntax is relatively simple. You tell LINQ to include the genres object, and then tell LINQ which fields it should associate. Paging Using LINQ LINQ also makes it much easier to include paging logic in your Web application by exposing the Skip and Take methods. The Skip method enables you to skip a defined number of records in the resultset. The Take method enables you to specify the number of records to return from the resultset. By calling Skip ,andthen Take , you can return a specific number of records from a specific location of the resultset. This is shown in Listing 9-17. Listing 9-17: Simple Paging using LINQ methods VB Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Dim movies = GetMovies() Dim genres = GetGenres() Dim query = (From m In movies _ Join g In genres On m.Genre Equals g.ID _ Continued 475 . 01/28/2008 2:09pm Page 4 75 Chapter 9: Querying with LINQ Finally, you can modify the Page Load event, including the LINQ query, to retrieve the Genres list and, using LINQ, join that to the Movies. grouping data, again using a SQL-like group syntax. To show how easy LINQ makes this, you can modify the original Listing 9-4 to use a LINQ query. The modified code is shown in Listing 9-12. Listing. SQL you can choose to order the results in either ascending or descending order, as shown in Listing 9-9. Listing 9-9: Controlling data ordering using LINQ VB Protected Sub Page_Load(ByVal sender

Ngày đăng: 05/07/2014, 18:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan