Using LINQ to SQL

13 594 0
Using LINQ to SQL

Đ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

Chapter 20 Using LINQ to SQL After completing this chapter, you will be able to:  Build LINQ queries that use the LINQ to SQL provider  Understand how LINQ to SQL prepares queries for processing  Determine when to use LINQ to SQL over LINQ to Entities LINQ is an extensible system, enabling a consistent querying experience against different data platforms. Sometimes these different systems overlap, providing access to the same target platform through different providers. SQL Server is one such database platform. LINQ to DataSet and LINQ to Entities both allow you to build LINQ queries that interact with data sourced from SQL Server, either directly (LINQ to Entities) or indirectly (LINQ to DataSet). LINQ to SQL, also included as a native LINQ provider within the .NET Framework, provides a third option for processing SQL Server data. This chapter focuses on the LINQ to SQL provider and the benefits it supplies to your data- focused application. In many ways, LINQ to SQL feels like LINQ to Entities, especially when using its class-generation feature. However, LINQ to SQL was built specifically to interact with SQL Server database tables, and its queries reflect that closer relationship. Note In October 2008, soon after the announcement of its plans for Visual Studio 10 and the related .NET Framework 4.0 release, Microsoft provided guidance on the future of its LINQ to SQL provider. This “Update on LINQ to SQL and LINQ to Entities Roadmap” blog entry posted by the ADO.NET team (http://blogs.msdn.com/b/adonet/archive/2008/10/29/update-on-linq-to- sql-and-linq-to-entities-roadmap.aspx) indicated that the Entity Framework would be the “rec- ommended data access solution for LINQ to relational scenarios.” The posting also included a commitment to evolve the LINQ to SQL product based on customer feedback. Note The exercises in this chapter all use the same sample project, a tool that makes queries using LINQ to SQL. Although you will be able to run the application after each exercise, the ex- pected results for the full application might not appear until you complete all exercises in the chapter. Dwonloaded from: iDATA.ws 332 Understanding the LINQ to SQL Provider LINQ to SQL is a LINQ provider that targets SQL Server databases. Its simple configuration needs and its focus on the logical organization of the underlying tables make it a useful tool for applications that need easy access to a specific SQL Server database. Comparing LINQ to SQL with LINQ to Entities The LINQ to SQL provider first appeared with the initial release of LINQ, part of Visual Studio 2008 and the .NET Framework 3.5. It preceded the release of LINQ to Entities, which was delivered as part of the .NET Framework 3.5 SP1. The two platforms share many similarities, including the following:  Modeling of data entities using an XML-based schema language  A Visual Studio–hosted visual designer that simplifies XML model creation  Generation of a language-specific class layer from the model  Support for database updates using custom stored procedures  Delayed query processing through LINQ-constructed SQL statements Despite these similarities, the two systems diverge significantly in many respects. These dif- ferences often help determine which of the two solutions is best for a given application. The two systems differ in four key areas:  Platform support The Entity Framework and its LINQ to Entities extension include support for a wide range of database platforms. In contrast, LINQ to SQL communicates only with SQL Server 2000 and later, including SQL Server Compact 3.5. Note The visual designer used to set up LINQ to SQL models does not work with SQL Server Compact 3.5.  Model focus LINQ to Entities queries focus on the Entity Framework conceptual model, which is an abstraction of the underlying logical database model. This model can differ significantly from the organization presented within the database. In LINQ to SQL, the model closely reflects the database tables that support it.  Overhead LINQ to SQL is extremely lightweight compared with its Entity Framework counterpart. EF’s three model layers allow for tremendous flexibility, but such design comes at a performance and memory overhead cost.  Extensibility While the query features available in both LINQ to Entities and LINQ to SQL are comparable, the Entity Framework’s design offers many opportunities for third- party enhancement that aren’t currently possible with LINQ to SQL. Dwonloaded from: iDATA.ws Chapter 20 Using LINQ to SQL 333 Using LINQ to SQL, especially when building models with its visual designer, is straightforward and often much quicker than setting up a LINQ to Entities environment. Microsoft’s official encouragement to use the Entity Framework option may help guide your decision, but for applications that have simple needs and access to SQL Server data, LINQ to SQL may be the best query platform. Understanding the Components of LINQ to SQL The focus of an Entity Framework model is the XML-based definition of the three different layers: conceptual, storage, and mapping. While LINQ to SQL can use an XML definition as the basis for a specific data implementation, the focus of each table definition is the entity class, a standard .NET class decorated with attributes from the System.Data.Linq.Mapping namespace. C# [Table(Name="UnitOfMeasure")] public class UnitOfMeasure { // ----- As defined in the database: // ID bigint // ShortName varchar(15) // FullName varchar(50) [Column(IsPrimaryKey = true)] public long ID; [Column] public string ShortName; [Column] public string FullName; } Visual Basic <Table(Name:="UnitOfMeasure")> Public Class UnitOfMeasure ' ----- As defined in the database: ' ID bigint ' ShortName varchar(15) ' FullName varchar(50) <Column(IsPrimaryKey:=True)> Public ID As Long <Column> Public ShortName As String <Column> Public FullName As String End Class Dwonloaded from: iDATA.ws 334 Microsoft ADO.NET 4 Step by Step Attributes, such as the TableAttribute and ColumnAttribute shown in this code block, inform LINQ to SQL how to map class members to tables and columns in the database. Additional attributes identify storage-level data types, intertable relationships, stored procedure defini- tions, and other key items that let the application communicate cleanly with the external data source. The System.Data.Linq.DataContext class binds these class definitions with actual data and acts much like the ObjectContext class in the Entity Framework. Derived versions of DataContext include instances of the decorated classes, forming a class-style representation of the actual database. C# public class SalesOrderLink : DataContext { // ----- Constructor establishes database connection. public SalesOrder(string connectionString): base(connectionString) {} // ----- Table definitions to link with database. public Table<Customer> Customers; public Table<OrderEntry> Orders; public Table<UnitOfMeasure> UnitsOfMeasure; } Visual Basic Public Class SalesOrderLink Inherits DataContext ' ----- Constructor establishes database connection. Public Sub New(ByVal connectionString As String) MyBase.New(connectionString) End Sub ' ----- Table definitions to link with database. Public Customers As Table(Of Customer) Public Orders As Table(Of OrderEntry) Public UnitsOfMeasure As Table(Of UnitOfMeasure) End Class After you have a defined context, using it with LINQ is a simple matter of creating an in- stance of the context and adding its exposed members to a query. Dwonloaded from: iDATA.ws Chapter 20 Using LINQ to SQL 335 C# using (SalesOrderLink context = new SalesOrderLink(connectionString)) { var results = from cu in context.Customers orderby cu.FullName select new { CustomerID = cu.ID, CustomerName = cu.FullName }; } Visual Basic Using context As New SalesOrderLink(connectionString) Dim results = From cu In context.Customers Order By cu.FullName Select CustomerID = cu.ID, CustomerName = cu.FullName End Using Except for the replacement of an ObjectContext by a DataContext, this query is identical to the first LINQ to Entities query included in Chapter 19, “Using LINQ to Entities.” Like its Entity Framework complement, LINQ to SQL uses the clauses in the query (in either the standard LINQ form shown here or one built with extension methods) to craft SQL state- ments that retrieve, project, filter, and sort the data returned by the query. Because of this, you are limited in the types of non-LINQ-To-SQL data that you can include in the query. Only data content and functionality that can be represented easily in a SQL statement are candi- dates for inclusion in a LINQ to SQL query. Despite this limitation, LINQ to SQL does a pretty good job at converting ordinary .NET ele- ments into SQL equivalents. Comparisons with null (C#) and Nothing (Visual Basic) translate into the expected IS NULL and IS NOT NULL forms. Using the Visual Basic Like pattern- matching operator results in a similar LIKE comparison in the generated SQL. Including the AddDays method on a date value within a LINQ to SQL query properly converts the expres- sion into one that uses the related DATEADD function in T-SQL. For a complete list of all .NET features that LINQ to SQL can use in database queries, see the “Data Types and Functions (LINQ to SQL)” entry in the Visual Studio online help. Using the Object Relational Designer Although you can handcraft your own entity classes, a better option for large databases (and even small ones) is to use the Object Relational (O/R) Designer, a drag-and-drop visual de- signer that generates LINQ to SQL classes based on a graphical database model. To use the O/R Designer, add a new “LINQ to SQL Classes” item to your Visual Basic or C# project. Dwonloaded from: iDATA.ws 336 Microsoft ADO.NET 4 Step by Step The Designer adds a .dbml file to your project, which hosts the data model in XML form. It also adds two support files: (1) a .dbml.layout file that stores some designer-specific informa- tion; and (2) a .designer.vb or .designer.cs file that holds the generated entity classes in either Visual Basic or C#. The Designer produces the designer file content as you make content- related changes to the visual design. You build your data model by dragging classes (entities) and associations (relationships) to the left pane of the designer surface. These entity and relationship instances are either generic forms from the Visual Studio Toolbox or existing database elements from the Server Explorer (or Database Explorer in Visual Studio Express Editions) tool window, as shown in Figure 20-1. You can also include database-level stored procedures and custom functions in the model by dragging them to the Designer’s right-side pane. FIGURE 20-1 The Designer after dragging and dropping an existing database table. Any changes you make to the model result in an immediate adjustment to the generated language-specific source code. You should not customize these generated class files because any future changes to the model will overwrite your changes. Note You can generate both the XML model and the class layer from a source database with- out using the visual designer. The Windows SDK installed with Visual Studio includes a program named SqlMetal.exe. This tool generates output similar to that of the visual designer, but it does so through a command-line interface. See the “SqlMetal.exe (Code Generation Tool)” entry in the Visual Studio online help for information on using this application. Dwonloaded from: iDATA.ws Chapter 20 Using LINQ to SQL 337 Building a LINQ to SQL Model 1. Open the “Chapter 20 CSharp” (C#) or “Chapter 20 VB” (Visual Basic) project from the installed samples folder. The project includes three Windows.Forms classes: OrderViewer, StatesByYear, and Switchboard. 2. Add a new LINQ to SQL data model to the application through the Project | Add New Item menu command. When the Add New Item form appears, select LINQ to SQL Classes from the list of templates and enter SalesOrder.dbml in the Name field. Click the Add button. 3. Visual Studio displays a blank Object Relational Designer. Open the Server Explorer (or Database Explorer) tool window (use the View | Server Explorer or View | Database Explorer menu if the window is not already present in Visual Studio) to display the contents of the book’s sample database. If the sample database is not already present in the Data Connections tree, use the Connect To Database toolbar button within the Server Explorer to locate the database. 4. Expand the sample database tree in the Server Explorer and drag the following items to the left half of the O/R Designer surface: Customer, OrderEntry, and StateRegion. Dwonloaded from: iDATA.ws 338 Microsoft ADO.NET 4 Step by Step As you drag each item, the Designer automatically creates associations between the entities based on foreign key references defined in the database schema. Click each en- tity and association, and then view the Properties panel to review the different settings associated with each element. 5. Drag the AdmittedInYear custom function from the Server Explorer tree to the right half of the designer surface. This adds a reference to a database-level function, allowing it to be used in your LINQ to SQL queries. Dwonloaded from: iDATA.ws Chapter 20 Using LINQ to SQL 339 6. Save changes to the file and close it. The Designer has already generated the class layer for the database objects dragged to the design surface. You can view the generated content by opening SalesOrder.designer.cs (C#) or SalesOrder.designer.vb (Visual Basic, although you may need to click the Show All Files button in the Solution Explorer to see the file). Using Custom Database Functions in Queries Although custom functions defined within a .NET application cannot participate directly in a LINQ to SQL query, these same queries can easily access functions written at the database level. When dragged to the design surface (as was done in the example shown previously), these T-SQL functions become part of the context that also hosts the entity classes. LINQ to Entities includes a similar feature, but it requires you to create local .NET stubs in your own code. With LINQ to SQL, the functions are ready to use in your queries; simply ref- erence the function name as a member of the instantiated context, passing the appropriate parameters as defined within the database. C# // ----- Assumes an AgedInvoices database function that // accepts a customer ID and a number of days, // returning a financial amount. var result = from cu in context.Customers orderby cu.FullName select new { cu.ID, cu.FullName, context.AgedInvoices(cu.ID, 90) }; Visual Basic ' ----- Assumes an AgedInvoices database function that ' accepts a customer ID and a number of days, ' returning a financial amount. Dim result = From cu In context.Customers Select cu.ID, cu.FullName, context.AgedInvoices(cu.ID, 90) Order By cu.FullName You can also call these functions directly, as long as a valid context exists. C# decimal pending = context.AgedInvoices(whichCustomer, 90); Visual Basic Dim pending As Decimal = context.AgedInvoices(whichCustomer, 90) Dwonloaded from: iDATA.ws 340 Microsoft ADO.NET 4 Step by Step Querying with LINQ to SQL: C# Note This exercise parallels exercises found in Chapter 19. The project is nearly identical in func- tionality and purpose, but it uses LINQ to SQL instead of LINQ to Entities to process database content. This exercise continues the previous exercise in this chapter. 1. Open the source code view for the General class. Locate the GetConnectionString func- tion; this is a routine that uses a SqlConnectionStringBuilder to create a valid connection string to the sample database. It currently includes the following statements: sqlPortion.DataSource = @"(local)\SQLExpress"; sqlPortion.InitialCatalog = "StepSample"; sqlPortion.IntegratedSecurity = true; Adjust these statements as needed to provide access to your own test database. 2. Open the source code view for the StatesByYear form. This form will access the AdmittedInYear database function, which was dragged into the model in the prior example. 3. Locate the StatesByYear_Load event handler; this is a routine that loads the data onto the form. Add the following code as the body of the routine: using (SalesOrderDataContext context = new SalesOrderDataContext(GetConnectionString())) { var result = from st in context.StateRegions where st.Admitted != null orderby st.Admitted.Value.Year select new { StateName = st.FullName, AdmitYear = st.Admitted.Value.Year, TotalAdmittedInYear = context.AdmittedInYear(st.Admitted) }; StateAdmittance.DataSource = result.ToList(); } In addition to calling the custom function AdmittedInYear, this query also uses != null as a condition, which will translate into the appropriate T-SQL comparison clause. 4. Run the program. When the Switchboard form appears, click States By Year. When the StatesByYear form appears, the results of the query will display in the form’s main grid. Dwonloaded from: iDATA.ws [...]... results of the query will display in the form’s main grid Chapter 20  Using LINQ to SQL 343 Summary This chapter introduced the LINQ to SQL query provider Although it shares many features with LINQ to Entities, its quick setup and close ties to SQL Server make it a useful choice for applications that target that platform LINQ to SQL sports its own visual designer: the Object Relational Designer, or... Chapter 20  Using LINQ to SQL 341 Querying with LINQ to SQL: Visual Basic Note  This exercise parallels exercises found in Chapter 19 It is nearly identical in functionality and purpose, but it uses LINQ to SQL instead of LINQ to Entities to process database content This exercise continues the previous exercise in this chapter... GetConnectionString function; this is a routine that uses a SqlConnectionStringBuilder to create a valid connection string to the sample database It currently includes the following statements: sqlPortion.DataSource = "(local)\SQLExpress" sqlPortion.InitialCatalog = "StepSample" sqlPortion.IntegratedSecurity = True Adjust these statements as needed to provide access to your own test database 2 Open the source code... approach or who need the automation support available through command-line utilities, the provider also includes SqlMetal.exe as an alternative to the visual experience Chapter 20 Quick Reference To Do This Include an entity class in a LINQ query Add the entity class to your project by writing its code, using the Object Relational Designer, or employing the SqlMetal.exe command-line tool Create a DataContext... context’s exposed entity collections within the From clauses of a LINQ query Include a custom SQL Server function within a LINQ to SQL query Drag the function to the right half of the Object Relational Designer surface or use equivalent code-based alternatives Create a DataContext instance that contains the function Call the function within a LINQ query ... StateName = st.FullName, AdmitYear = st.Admitted.Value.Year, TotalAdmittedInYear = context.AdmittedInYear(st.Admitted) Order By AdmitYear StateAdmittance.DataSource = result.ToList End Using In addition to calling the custom function AdmittedInYear, this query also uses IsNot Nothing as a condition, which will translate into the appropriate T -SQL comparison clause 4 Run the program When the Switchboard... StatesByYear form This form will access the AdmittedInYear database function, which was dragged into the model in the prior example 342 Microsoft ADO.NET 4 Step by Step 3 Locate the StatesByYear_Load event handler; this is a routine that loads the data onto the form Add the following code as the body of the routine: Using context As New SalesOrderDataContext(GetConnectionString()) Dim result = From st In . 20 Using LINQ to SQL After completing this chapter, you will be able to:  Build LINQ queries that use the LINQ to SQL provider  Understand how LINQ to. a useful tool for applications that need easy access to a specific SQL Server database. Comparing LINQ to SQL with LINQ to Entities The LINQ to SQL provider

Ngày đăng: 03/10/2013, 00:20

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

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

Tài liệu liên quan