1. Trang chủ
  2. » Công Nghệ Thông Tin

Beginning Microsoft Visual C# 2008 PHẦN 8 docx

135 279 0

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

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 135
Dung lượng 1,54 MB

Nội dung

Chapter 27: LINQ to SQL 909 ); foreach (Order o in item.Orders) { Console.WriteLine(“\t\t{0}\t{1}”, o.OrderID, o.OrderDate); } }; Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); } 6. Compile and execute the program (you can just press F5 for Start Debugging). You will see the information for customers in the U.S.A. and their orders as follows (this is the last part of the output; the first part scrolls off the top of the console window): Customer: Trail’s Head Gourmet Provisioners Kirkland, WA 3 orders: Order ID Order Date 10574 6/19/1997 12:00:00 AM 10577 6/23/1997 12:00:00 AM 10822 1/8/1998 12:00:00 AM Customer: White Clover Markets Seattle, WA 14 orders: Order ID Order Date 10269 7/31/1996 12:00:00 AM 10344 11/1/1996 12:00:00 AM 10469 3/10/1997 12:00:00 AM 10483 3/24/1997 12:00:00 AM 10504 4/11/1997 12:00:00 AM 10596 7/11/1997 12:00:00 AM 10693 10/6/1997 12:00:00 AM 10696 10/8/1997 12:00:00 AM 10723 10/30/1997 12:00:00 AM 10740 11/13/1997 12:00:00 AM 10861 1/30/1998 12:00:00 AM 10904 2/24/1998 12:00:00 AM 11032 4/17/1998 12:00:00 AM 11066 5/1/1998 12:00:00 AM Press Enter/Return to continue As before, press Enter/Return to finish the program and make the console screen disappear. How It Works You modified your previous program instead of creating a new program from scratch so you did not have to repeat all the steps to create the Northwind.dbml LINQ to SQL mapping source file (note that the sample code has separate projects, each with its own instance of Northwind.dbml ). By dragging the Orders table in from the Database Explorer window, you added the Order class to the Northwind.dbml source file to represent the Orders table in your mapping of the Northwind database. The O/R Designer also detected the relationship in the database between Customers and Orders, adding an Orders collection member to the Customer class to represent the relationship. All this was done automatically, as when you add new controls to a form. c27.indd 909c27.indd 909 3/24/08 5:23:53 PM3/24/08 5:23:53 PM Part IV: Data Access 910 If you look before and after you add a database object to the O/R Designer pane, you will see that the class definition for the added object(s) appears in the Northwind.designer.cs generated source file. As noted before, do not modify this generated source file; use it only for reference purposes. Next, you added the newly available Orders member to the select clause of the query: select new { ID=c.CustomerID, Name=c.CompanyName, City=c.City, State=c.Region, Orders=c.Orders }; Orders is a special typed LINQ set ( System.Data.Linq.EntitySet < Order > ) that represents the relationship between two tables in the relational database. It implements the IEnumerable/ IQueryable interfaces so it can be used as a LINQ data source itself or iterated with a foreach statement just like any collection or array. Like the Table object shown in the previous example, the EntitySet is similar to a typed collection of Order objects (like a List < Order > ), but only those orders submitted by a particular customer will appear in the EntitySet member for a particular Customer instance. The Order objects in the customer ’ s EntitySet member correspond to the order rows in the database having the same customer ID as that customer ’ s ID. Navigating the relationship simply involves building a nested foreach statement to iterate through each customer and then each customer ’ s orders: foreach (var item in queryResults) { Console.WriteLine( “Customer: {0} {1}, {2}\n{3} orders:\tOrder ID\tOrder Date”, item.Name, item.City, item.State, item.Orders.Count ); foreach (Order o in item.Orders) { Console.WriteLine(“\t\t{0}\t{1}”, o.OrderID, o.OrderDate); } }; Rather that just use the default ToString() formatting, you format the output for readability so you can show the hierarchy properly with the list of orders under each customer. The format string “ Customer: {0} {1}, {2}\n{3} orders:\tOrder ID\tOrder Date ” has a placeholder for the name, city, and state of each customer on the first line, and then prints a column header for that customer ’ s orders on the next line. You use the LINQ aggregate Count() method to print the count of the number of that customer ’ s orders, and then print out the order ID and order date on each line in the nested foreach statement: Customer: White Clover Markets Seattle, WA 14 orders: Order ID Order Date 10269 7/31/1996 12:00:00 AM 10344 11/1/1996 12:00:00 AM c27.indd 910c27.indd 910 3/24/08 5:23:53 PM3/24/08 5:23:53 PM Chapter 27: LINQ to SQL 911 The formatting is still a bit rusty in that you see the time of the order when all that really matters is the date. However, you will get a chance to clean that up in the next example. Drilling Down Further with LINQ to SQL To get to the interesting data of how much each customer is spending, you need to add one more level of detail and drill down into the details of each order, using the Order Details table. Again, LINQ to SQL and the O/R Designer make this very easy to do, as you will see in the following Try It Out. Try It Out Drilling Down Further LINQ to SQL In Visual C# 2008, modify the project for the previous example, BegVCSharp_27_1_ FirstLINQtoSQLQuery, in the directory C:\BegVCSharp\Chapter27 as shown in the following steps: 1. Click on the Order Details table in the Database Explorer window and drag it into the Northwind.dbml pane as shown in Figure 27 - 16 . Figure 27-16 c27.indd 911c27.indd 911 3/24/08 5:23:53 PM3/24/08 5:23:53 PM Part IV: Data Access 912 2. Compile the project so that the Order_Detail object appears when you start entering code in the next step. 3. Open the main source file Program.cs . In the Main() method the query should appear like this: static void Main(string[] args) { NorthwindDataContext northWindDataContext = new NorthwindDataContext(); var queryResults = from c in northWindDataContext.Customers where c.Country == “USA” select new { ID=c.CustomerID, Name=c.CompanyName, City=c.City, State=c.Region, Orders=c.Orders }; 4. Modify the foreach clause to print the query results: foreach (var item in queryResults) { Console.WriteLine( “Customer: {0} {1}, {2}\n{3} orders: Order ID\tOrder Date\tTotal Amount”, item.Name, item.City, item.State, item.Orders.Count); foreach (Order o in item.Orders) { Console.WriteLine( “\t{0,10}\t{1,10}\t{2,10}”, o.OrderID, o.OrderDate.Value.ToShortDateString(), o.Order_Details.Sum(od = > od.Quantity * od.UnitPrice) .ToString(“C2”)); } }; Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); } 5. Compile and execute the program (you can just press F5 for Start Debugging). Again, the result shown here is just the last part of the output): Customer: Trail’s Head Gourmet Provisioners Kirkland, WA 3 orders: Order ID Order Date Total Amount 10574 6/19/1997 $764.30 10577 6/23/1997 $569.00 10822 1/8/1998 $237.90 c27.indd 912c27.indd 912 3/24/08 5:23:54 PM3/24/08 5:23:54 PM Chapter 27: LINQ to SQL 913 Customer: White Clover Markets Seattle, WA 14 orders: Order ID Order Date Total Amount 10269 7/31/1996 $676.00 10344 11/1/1996 $2,856.00 10469 3/10/1997 $1,125.50 10483 3/24/1997 $704.00 10504 4/11/1997 $1,388.50 10596 7/11/1997 $1,476.10 10693 10/6/1997 $2,334.00 10696 10/8/1997 $996.00 10723 10/30/1997 $468.45 10740 11/13/1997 $1,770.00 10861 1/30/1998 $3,523.40 10904 2/24/1998 $1,924.25 11032 4/17/1998 $8,902.50 11066 5/1/1998 $928.75 Press Enter/Return to continue As you did before, press Enter/Return to finish the program and make the console screen disappear. How It Works You modified your previous program instead of creating a new program from scratch so you did not have to repeat all the steps to create the Northwind.dbml LINQ to SQL mapping source file. You dragged the Order Details table in from the Database Explorer window, adding the Order_Detail class to the Northwind.dbml source file and adding an Order_Details_ collection member to the Order class to represent the relationship between Orders and Order Details . Because class names and members in C# cannot contain spaces, the O/R Designer added an underscore to form the names Order_Detail and Order_Details . Like the Orders member of Customer itself, the Order_Details member of Orders is an EntitySet representing the relationship. You did not have to modify the from where select clauses of the previous LINQ query at all; instead, all the changes are confined to the foreach processing loop: foreach (var item in queryResults) { Console.WriteLine( “Customer: {0} {1}, {2}\n{3} orders: Order ID\tOrder Date\tTotal Amount”, item.Name, item.City, item.State, item.Orders.Count); foreach (Order o in item.Orders) { Console.WriteLine( “\t{0,10}\t{1,10}\t{2,10}”, o.OrderID, o.OrderDate.Value.ToShortDateString(), o.Order_Details.Sum(od = > od.Quantity * od.UnitPrice) .ToString(“C2”)); } }; c27.indd 913c27.indd 913 3/24/08 5:23:54 PM3/24/08 5:23:54 PM Part IV: Data Access 914 You added “ Total Amount ” to the end of the header for each customer in the first line of the outer foreach loop. In the inner foreach loop you cleaned up the formatting of each entry by adding a field width of 10 to each Console.Writeline() placeholder so that it reads “ \t{0,10}\t{1,10}\ t{2,10} ” . In the list of fields, you passed the OrderID , and the OrderDate formatted as a short date string to eliminate the unused time portion of the OrderDate . The total for each order is calculated from the Order_Details . Things get a bit interesting here, but you ’ ve already seen each element in the previous chapter. To get the sum of all the order details for a single order, you use the LINQ Sum() aggregate operator, passing a lambda expression ( od = > od.Quantity * od.UnitPrice ) that calculates the total price of each order (the subtotal for each order detail is the quantity times the unit price (that is, three widgets @ $2 each = $6)). You format this total as currency with two decimal places ( “ C2 “ ), and that finishes the example. Grouping, Ordering, and Other Advanced Queries in LINQ to SQL Now that you know how the total spending for each customer is calculated, you may begin to have questions at a higher level. Which customers are buying the most? What regions or countries are they located in? What products are selling best? To answer decision support questions such as these, grouping and ordering are required. The group and orderby operations are the same in your code in LINQ to SQL as they are in LINQ to Objects, but use SQL data sources for which LINQ can take advantage of the underlying group and orderby capabilities in the SQL database, depending on your query construction. In the next example, you try this out by constructing a query to find what countries have had the largest total sales. Try It Out Grouping, Ordering, and Other Advanced Queries In Visual C# 2008, modify the project for the previous example, BegVCSharp_27_1_ FirstLINQtoSQLQuery, in the directory C:\BegVCSharp\Chapter27 as shown in the following steps: 1. Open the main source file Program.cs . Replace the LINQ query in the Main() method with the following queries: static void Main(string[] args) { NorthwindDataContext northWindDataContext = new NorthwindDataContext(); var totalResults = from c in northWindDataContext.Customers select new { Country = c.Country, Sales = c.Orders.Sum(o = > c27.indd 914c27.indd 914 3/24/08 5:23:54 PM3/24/08 5:23:54 PM Chapter 27: LINQ to SQL 915 o.Order_Details.Sum(od = > od.Quantity * od.UnitPrice) ) }; var groupResults = from c in totalResults group c by c.Country into cg select new { TotalSales = cg.Sum(c = > c.Sales), Country = cg.Key } ; var orderedResults = from cg in groupResults orderby cg.TotalSales descending select cg ; 2. Continue to modify the Main() method in Program.cs by replacing the foreach loop following the LINQ query with the code shown here: Console.WriteLine(“Country\t\tTotal Sales\n \t ”); foreach (var item in orderedResults) { Console.WriteLine(“{0,-15}{1,12}”, item.Country, item.TotalSales.ToString(“C2”)); } Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); } 3. Compile and execute the program (you can just press F5 for Start Debugging). You will see the total sales by country in descending order as follows: Country Total Sales USA $263,566.98 Germany $244,640.63 Austria $139,496.63 Brazil $114,968.48 France $85,498.76 Venezuela $60,814.89 UK $60,616.51 Sweden $59,523.70 Ireland $57,317.39 Canada $55,334.10 Belgium $35,134.98 Denmark $34,782.25 Switzerland $32,919.50 Mexico $24,073.45 Finland $19,778.45 c27.indd 915c27.indd 915 3/24/08 5:23:55 PM3/24/08 5:23:55 PM Part IV: Data Access 916 Spain $19,431.89 Italy $16,705.15 Portugal $12,468.65 Argentina $8,119.10 Norway $5,735.15 Poland $3,531.95 Press Enter/Return to continue As before, press Enter/Return to finish the program and make the console screen disappear. How It Works Again you modified your previous program to reuse the Northwind.dbml LINQ to SQL mapping. For this example you did not have to add any classes to Northwind.dbml because you used the existing mapping classes for Customer , Order ,and Order_Details . You replaced the previous LINQ query with three new queries using the same data source as before but processing the results very differently. The first LINQ query is similar to previous queries in this chapter, using northWindDataContext .Customers as the data source: var totalResults = from c in northWindDataContext.Customers select new { Country = c.Country, Sales = c.Orders.Sum(o = > o.Order_Details.Sum(od = > od.Quantity * od.UnitPrice) ) }; For this query you do not want to restrict the results to the U.S.A. only, so there is no where clause. Instead of the Region property, you select Country because this queries groups and orders by country. You do not select the customer ID , Name , or City because these are not used in the result and it is inefficient to ask for more data from the database than you are going to use. The Sum() operation using the lambda expression od = > od.Quantity * od.UnitPrice to get the sum of all the order details is now moved to the LINQ query itself. Next, you specify a group query to group the total sales by country, using the preceding query results as the data source: var groupResults = from c in totalResults group c by c.Country into cg select new { TotalSales = cg.Sum(c = > c.Sales), Country = cg.Key } ; This query is very similar to the group query you created for LINQ to Objects in the previous chapter, using the country as the key to group results and by summing the total sales (in this case, Sum() is adding up the customer total sales for all customers within a country) the operation is nested inside another Sum() to sum up the sales for all the Orders of each Customer . c27.indd 916c27.indd 916 3/24/08 5:23:55 PM3/24/08 5:23:55 PM Chapter 27: LINQ to SQL 917 For the last query, you order the results with the ordered results query, using the group query as the data source. A separate query is needed for this because group queries can be ordered only by the key field: var orderedResults = from cg in groupResults orderby cg.TotalSales descending select cg ; Finally, you do some output formatting, printing a header for the Country and Total Sales columns in the result, and then in the foreach processing loop printing the two columns in justified format (left - justified in a 15 - character - wide field for the Country , right - justified in a 12 - character - wide field for the Total Sales : Console.WriteLine(“Country\t\tTotal Sales\n \t ”); foreach (var item in orderedResults) { Console.WriteLine(“{0,-15}{1,12}”, item.Country, item.TotalSales.ToString(“C2”)); } Displaying Generated SQL If you are familiar with SQL databases you may be wondering what SQL database commands are being generated by LINQ to SQL. Even if you are not familiar with SQL, it is sometimes instructive to look at the generated SQL to understand how LINQ to SQL is interacting with the database (and perhaps to appreciate what LINQ to SQL is doing by taking care of writing the complex SQL for you!) . In the following Try It Out, you will modify the previous group query example to display the generated SQL, and then look at how it is executed. Try It Out Displaying Generated SQL Follow these steps to create the example in Visual C# 2008: 1. Modify the project for the previous example, BegVCSharp_27_1_FirstLINQtoSQLQuery, in the directory C:\BegVCSharp\Chapter27 as shown in the following steps. 2. Open the main source file Program.cs . Add the highlighted lines to the Main() method: static void Main(string[] args) { NorthwindDataContext northWindDataContext = new NorthwindDataContext(); var totalResults = from c in northWindDataContext.Customers select new c27.indd 917c27.indd 917 3/24/08 5:23:55 PM3/24/08 5:23:55 PM Part IV: Data Access 918 { Country = c.Country, Sales = c.Orders.Sum(o = > o.Order_Details.Sum(od = > od.Quantity * od.UnitPrice) ) }; Console.WriteLine(“ SQL for totalResults query ”);; Console.WriteLine(totalResults); Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); var groupResults = from c in totalResults group c by c.Country into cg select new { TotalSales = cg.Sum(c = > c.Sales), Country = cg.Key } ; Console.WriteLine(“ SQL for groupResults query ”);; Console.WriteLine(groupResults); Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); var orderedResults = from cg in groupResults orderby cg.TotalSales descending select cg ; Console.WriteLine(“ SQL for orderedResults query ”);; Console.WriteLine(groupResults); Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); Console.WriteLine(“Country\t\tTotal Sales\n \t ”); foreach (var item in orderedResults) { Console.WriteLine(“{0,-15}{1,12}”, item.Country, item.TotalSales.ToString(“C2”)); } Console.WriteLine(“Press Enter/Return to continue ”); Console.ReadLine(); } 3. Compile and execute the program (you can just press F5 for Start Debugging). You will see the following SQL output for the first query on the console screen: SQL for totalResults query SELECT [t0].[Country], ( SELECT SUM([t4].[value]) FROM ( SELECT SUM([t3].[value])( SELECT SUM((CONVERT(Decimal(29,4),[t2].[Quantity])) * [t2].[UnitPrice]) c27.indd 918c27.indd 918 3/24/08 5:23:55 PM3/24/08 5:23:55 PM [...]... the database and navigating relationships Well, there’s more good news for you! Visual C# 20 08 includes data binding in the forms designers that works with LINQ to SQL so that you don’t have to have write detailed code to get data from your end-user forms to the database classes You can point-and-click in Visual C# 20 08 to generate code for a sophisticated graphical database application that works... 3/24/ 08 5:23:56 PM Part IV: Data Access Try It Out Data Binding with LINQ To SQL Follow these steps to create the example in Visual C# 20 08: 1 Create a new Windows Forms project called BegVCSharp_27_2_LINQtoSQLDataBinding in the directory C:\BegVCSharp\Chapter27 2 Add the LINQ to SQL class Northwind.dbml and connect to the Northwind database as you did in the first LINQ to SQL query example at the beginning. .. Highlights of this chapter included the following: ❑ The concept of object-relational mapping (ORM) and how LINQ to SQL implements this concept for C# ❑ Learning to use the O/R Designer in Visual C# 20 08 to create objects for a specific database 929 c27.indd 929 3/24/ 08 5:23:59 PM Part IV: Data Access ❑ Using LINQ to SQL queries with the objects created by the O/R Designer ❑ Navigating relationships between... LINQ, with new facilities such as the forthcoming ADO.NET for Entities, which will ship after Visual Studio 20 08 ADO.NET for Entities is an advanced interface targeted at expert ADO.NET developers and is a subject beyond the scope of this book Still evolving, it is not officially part of Visual Studio 20 08 Design Goals of ADO.NET Let’s quickly look at the design goals of ADO.NET: ❑ Simple access to... create some simple projects and start using the ADO.NET classes c 28. indd 933 3/24/ 08 5:24:34 PM Part IV: Data Access What Is ADO.NET? ADO.NET is the name for the set of classes you use with C# and the NET Framework to access data in a relational, table-oriented format This includes relational databases such as Microsoft SQL Server and Microsoft Access, as well as other databases and even nonrelational... Figure 27- 18 Add New Data Source as shown in Figure 27- 18 922 c27.indd 922 3/24/ 08 5:23:57 PM Chapter 27: LINQ to SQL 6 In the Data Source Configuration Wizard dialog, click Object as the data source type as shown in Figure 27-19 Then click Next Figure 27-19 7 Choose the Customer object (see Figure 27-20) and then click Finish Figure 27-20 923 c27.indd 923 3/24/ 08 5:23:57 PM Part IV: Data Access 8 Click... let’s look at the actual ADO.NET classes themselves 936 c 28. indd 936 3/24/ 08 5:24:35 PM Chapter 28: ADO.NET and LINQ over DataSet Over view of ADO.NET Classes and Objects The diagram in Figure 28- 1 shows the basic classes in ADO.NET Note that this is not an inheritance diagram It shows the relationships between the most commonly used classes Figure 28- 1 The classes are divided into NET data provider objects... table, such as OrderID or CustomerName ❑ DataRow object: This represents one row of related data from a table, such as a particular customer ’s CustomerID, name, address, and so on 9 38 c 28. indd 9 38 3/24/ 08 5:24:36 PM Chapter 28: ADO.NET and LINQ over DataSet DataRelation Object The DataRelation object represents the relationship between two tables via a shared column; for example, the Orders table might... database Luckily, it is very easy to turn on the Save functionality, as you will see in this Try It Out Try It Out Updating Bound Data with LINQ to SQL Follow these steps to create the example in Visual C# 20 08: 1 Modify the existing Windows forms project BegVCSharp_27_2_LINQtoSQLDataBinding in the directory C:\BegVCSharp\Chapter27 2 In the Form1.cs design window, double-click on the Save button in the... Connectivity (ODBC) ODBC was developed by Microsoft in collaboration with other companies in the early 1990s ODBC provided a common set of functions that developers could use against any database system These functions were translated into database-specific function calls by drivers for that specific database system 934 c 28. indd 934 3/24/ 08 5:24:34 PM Chapter 28: ADO.NET and LINQ over DataSet This solved . $263,566. 98 Germany $244,640.63 Austria $139,496.63 Brazil $114,9 68. 48 France $85 ,4 98. 76 Venezuela $60 ,81 4 .89 UK $60,616.51 Sweden $59,523.70 Ireland $57,317.39 Canada $55,334.10 Belgium $35,134. 98 Denmark. 10/30/1997 $4 68. 45 10740 11/13/1997 $1,770.00 1 086 1 1/30/19 98 $3,523.40 10904 2/24/19 98 $1,924.25 11032 4/17/19 98 $8, 902.50 11066 5/1/19 98 $9 28. 75 Press Enter/Return to continue As you did. 10696 10 /8/ 1997 12:00:00 AM 10723 10/30/1997 12:00:00 AM 10740 11/13/1997 12:00:00 AM 1 086 1 1/30/19 98 12:00:00 AM 10904 2/24/19 98 12:00:00 AM 11032 4/17/19 98 12:00:00 AM 11066 5/1/19 98 12:00:00

Ngày đăng: 09/08/2014, 14:21

TÀI LIỆU CÙNG NGƯỜI DÙNG

  • Đang cập nhật ...

TÀI LIỆU LIÊN QUAN