Understanding Language Integrated Query (LINQ)

Language Integrated Query (LINQ) is a query translation pipeline that has been introduced as part of the C# 3.0 library. It is a language that is integrated into the language itself. It is an extension of C#, and provides a simplified framework for accessing relational data in a strongly typed and object-oriented way. You can even use LINQ to query data from other data sources—XML, objects, and, collections.

The Line of Business (LOB) applications are data driven, and they mostly depend on CRUD (Create, Read, Update, and Delete) operations on data. The ORMs are built with this in mind, and provide a simple way to access your database by providing data consistency and data integrity. With some awesome features, such as support for anonymous methods, enumerators and yield, the lambda expression, extension methods, and anonymous types, LINQ is basically a sort of Domain Specific Language (DSL) for C# or VB.NET. Support for IQueryable, IEnumerable, Func delegates, and the lambda expression in the newer versions of the .NET Framework help in promoting this feature.

LINQ is a part of the new versions of the C# and VB.NET compilers, and it comes with a powerful set of operators to ease the task of querying different data sources, such as the SQL Server and XML.

A query language is one that is used to query data in our applications. Before LINQ arrived, we used PL-SQL and T-SQL to query data from databases. However, none of these were type safe, and they also didn't have compile-time checks to verify whether the statements were correct at the time of compilation. In LINQ, we have compile-time checks and type safety; hence, your queries will be verified for accuracy at the compile time itself!

LINQ is a new useful feature, available as part of C# 3.0, and allows you to integrate queries right into your programs. It is an extension to the C# language and provides a simplified framework for accessing relational data in a strongly typed and object-oriented manner. Apart from being type safe and the ability to check queries at the time of compilation, you can debug your LINQ queries comfortably—a very important feature indeed. It should be noted that Visual Studio has some limitations for the debugging support of LINQ code. For example, "Edit and continue" is not supported; you are not allowed to step into the predicate code in the debug mode, and the code that gets compiled to the expression tree isn't within the control of the debugger.

LINQ provides support for lazy loading, compiled queries, and extension methods. Extension methods, as the name suggests, are those that enable you to provide extensions to an existing type. These enable you to add new methods to existing types without the need of creating new derived types. An example of an extension method is given as follows:

public static class EmployeeExtensions
{
  public IQueryable<T> IsActive<T>(this IQueryable<T> source)
  where T : Employee
  {
    return source.Where(e => (e.JoiningDate < DateTime.Now)&& (e.LeavingDate == DateTime.Now)&& e.IsActive == true);
  }
}

Note

There is a way to work around debugging the predicate code though. What you can do is replace the predicate code with a call to a method that contains the predicate code, that is, by creating a wrapper method.

The LINQ library comprises the following important namespaces:

  • System.Linq: This namespace provides a set of classes and interfaces supporting LINQ queries
  • System.Data.Linq: This namespace provides a set of classes and interfaces for interacting with the relational database

Data source controls

A data source control acts like a layer in between your data source and the data-bound control. Data bound controls can be any control that actually interacts with the end user while consuming the data services provided by the data source control to which it is bound. It defines certain methods and properties that perform data-specific operations, such as insert, delete, update, and select over the data at the data source while abstracting the data source. Following are the various kinds of DataSource controls that are shipped with the ASP.NET 4.0.

ObjectDataSource

ObjectDataSource control works with in-memory collections. It defines properties, such as InsertMethod, DeleteMethod, UpdateMethod, and SelectMethod, which perform basic data storage and retrieval operations. Appropriate methods must be created and mapped to these properties to perform the required task. When one of these properties is used, the ObjectDataSource control actually creates the instance and invokes the appropriate method, and it is destroyed as soon as it completes its execution phase. ObjectDataSource is usually used in the business layer of your application, which assists you to directly bind to the data-bound controls on the presentation layer.

SqlDataSource

The SqlDataSource control allows you to perform standard data operations, such as insert, update, delete, and select on the data persisting in your relation database. The SqlDataSource control is not meant only for the SQL Server database, and can work with any managed ADO.NET provider, which means that you can use the SqlDataSource control with different relational data sources. The SqlDataSource control defines properties, such as InsertCommand, DeleteCommand, UpdateCommand, and SelectCommand for performing standard data operations, such as insert, delete, update, and select on the data. The command properties need appropriate queries to be set before using them. When a data control that connects to a SqlDataSource control is updated, the SqlDataSource control creates update parameters for all the columns even though few columns are updated. The control also supports caching capabilities, which assist in improving the performance of the application.

SiteMapDataSource

The SiteMapDataSource control allows you to bind the site map of your website. The site map can represent a hierarchical structure. The SiteMapDataSource control needs an appropriate root node to be specified in a given hierarchy. The SiteMapDataSource control contains properties that allow you to specify the node locations. Primarily, the SiteMapDataSource control is used for the purpose of data navigation, which means you cannot perform standard data operations, such as insert, update, delete, sorting, and paging of the data.

XMLDataSource

The XmlDataSource control is another kind of DataSourceControl. Basically, it represents the data that is in the form of XML. You can access the XML data from the XmlDataSource control by connecting the control to a XML file or XML data embedded as a string within the data source control. Caching in the XmlDataSource control is enabled by default for increasing the performance. You can perform standard data operations, such as insert, delete, update, and select, over the XML data that is represented by the XmlDataSource control. However, operations like sorting and paging are not supported by the XmlDataSource control. The control also provides support for applying XML transformations through an XML stylesheet.

LinqDataSource

LinqDataSource control is a new control that has been introduced in ASP.NET 3.5. It extends DataSourceControl and resides in the System.Web.UI.WebControls namespace. It provides a new approach for binding LINQ models to the web controls in your ASP.NET applications. The LinqDataSource control provides properties and events using which you can perform operations such as selecting, filtering, grouping, and ordering of a LINQ data source.

The LinqDataSource data control provides a flexible mechanism to build a data control with a wizard-based workflow. It allows you to perform CRUD operations on the data over a LINQ model with minimal need of writing SQL queries.

The syntax remains the same for whatever data source you use. There is no need to define the queries for the select, delete, update, and insert operations manually.

LINQ provides the concept of a unified data model; all you have to do is focus on your logic, because the LinqDataSource control automatically creates the necessary commands for your needs.

The following example of code shows the syntax of using the LinqDataSource control:

<asp:LinqDataSource ID="ldsPurchaseOrderDetails" runat="server" ContextTypeName=" AdventureWorksDataContext" TableName="PurchaseOrderDetails" Select="new (ProductID, UnitPrice, StockedQty)">
</asp:LinqDataSource>

In the previous code snippet, ContextTypeName refers to the DataContext class. Note that a DataContext class is created automatically when you create a data model using the LINQ to SQL designer in Visual Studio 2013 IDE. The TableName property refers to a collection of the PurchaseOrderDetail type. The Select property extracts a new anonymous type containing the ProductID, UnitPrice, and StockedQty properties. In conjunction with the previous data source control, data controls such as DetailsView, GridView, or ListView can be used to bind the data. A simple syntax that represents the binding mechanism of a GridView's data source to the LinqDataSource control is as follows:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"  DataSourceID="ldsPurchaseOrderDetails">
  <Columns>
    <asp:BoundField DataField="ProductID" HeaderText="ProductID" ReadOnly="True" SortExpression="ProductID" />
    <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" ReadOnly="True" SortExpression="UnitPrice" />
    <asp:BoundField DataField="StockedQty" HeaderText="StockedQty" ReadOnly="True" SortExpression="StockedQty" />
  </Columns>
</asp:GridView>

The following example shows how the LinqDataSource control can be used for binding the in-memory objects to a DropDownList control:

<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="Packt.Customer" TableName="FirstNames"></asp:LinqDataSource>
<asp:DropDownList DataSourceID="LinqDataSource1" runat="server" ID="DropDownList1"></asp:DropDownList>

In the Default.aspx.cs file, we will create a class named Customer. The class representation is as as follows:

public class Customer
  {
    List<string> names = new List<string>();
    public Customer()
    {
      names.Add("Joydip");
      names.Add("Sriram");
      names.Add("Sandeep");
      names.Add("Ramesh");
      names.Add("Sandy");
      names.Add("John");
    }
    public List<string> FirstNames { get { return names; } }
  }

The following figure illustrates the LINQ architecture:

LinqDataSource

LINQ to XML

"LINQ to XML" maps your LINQ queries or LINQ statements to the corresponding XML data sources. It helps you to use the LINQ standard query operators to retrieve XML data. LINQ to XML is commonly known as XLINQ. You can also use LINQ to query your in-memory collections and business entities (in-memory objects that contain data related to a particular entity) seamlessly.

Support for LINQ to XML is provided in the System.XML.Linq namespace. An example that illustrates how LINQ to XML can be used to create a data document is as follows:

public static void CreateEmployeeDataSheet()
{
  XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"),new XComment("Employee Data Sheet"),new XElement("employees",new XElement("Employee",new XAttribute("ID", 1),
    new XAttribute("Salaried", "false"),new XElement("First Name", "Joydip"),new XElement("Last Name", "Kanjilal"),new XElement("Joining Date", "02/01/2013")),new XElement("Employee",new XAttribute("ID", 1),new XAttribute("Salaried", "false"),new XElement("First Name", "Peter"),new XElement("Last Name", "Ward"),new XElement("Joining Date", "07/01/2013"))
    )
  );
}

LINQ to SQL

Similar to XLINQ (for querying your XML documents), you also have DLINQ which is an implementation of LINQ that allows you to query your databases. LINQ to SQL, or DLINQ as it is called, is actually a very simple ORM tool. It is not a complete ORM tool, because it lacks some of the features that an ORM has. It doesn't support state management and data generation.

Note

To use LINQ in your programs, you must add a reference to System.Core.dll and specify the System.Linq namespace in the using statement.

LINQ to Objects

LINQ to Objects is another flavor of LINQ that is used to query in-memory collections of objects. Note that LINQ to Objects works with the T:System.Collections.IEnumerable or T:System.Collections.Generic in-memory objects or a collection of objects. Note that LINQ to Objects is implied as part of LINQ; it is a part of the new versions of the .NET Framework. You need not specify any separate namespaces to write your LINQ to Objects queries.

LINQ to Entities

The ADO.NET Entity Framework is a type of ORM. It is a development platform that provides a layer of abstraction on top of the relational or logical model. In doing so, it isolates the object model of the application from the way the data is actually stored in the relational store. Developers can use the ADO.NET Entity Framework to program against an object model, rather than the logical or relationship model.

This level of abstraction is achieved using the Entity Data Model (EDM)—an extended entity relationship model. The EDM reduces the dependency of your domain object model on the database schema of the data store in use. Developers can use the ADO.NET Entity Framework to work with domain-specific properties, such as employee name, employee address, and contact details, without having to be concerned with how the actual data is stored and represented in the underlying data store. The framework can take care of the necessary translations to either retrieve data from your data store or perform insertions, updates, and deletions.

LINQ to Entities is used to query data exposed by the EDM. LINQ to Entities enables you to query your business objects in a strongly typed manner. You can use it to query business objects or collections of business objects from the conceptual data model, that is, the EDM. LINQ to Entities uses ObjectServices to query data from the EDM.

LINQ to Entities uses the Object Services infrastructure to query data from the conceptual model. The ObjectContext and ObjectQuery classes are two of the most important classes that you use when working with LINQ to Entities. The ObjectContext class is used to compose an ObjectQuery instance. The generic ObjectQuery class actually represents an entity or collection of typed entity instances. It should be noted that LINQ to Entities queries get internally translated to canonical query trees. These, in turn, are converted to corresponding SQL queries internally in a predefined form by your underlying database.

The relation between LINQ to Entities and the Entity Framework is shown in the following figure:

LINQ to Entities

Working with service operations in LINQ

Service operations are the methods that can be called over the data services, which have the same visibility as the entity sets. The IDataServiceConfiguration class supports the user-defined methods to be exposed over the data service. To do this, we need to set a WebGet attribute to this function and the access rule in the data service configuration of the data service.

The following code snippet illustrates a DataService class:

[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class GenericCollections : DataService<AddressSet>
{
  [WebGet]
  public IQueryable<Address> GetAddresssByCity(string City)
  {
    var addressquery = from addr in this.CurrentDataSource.Addresses
    where addr.City.Equals(City)
    select addr;
    return addressquery;
  }

  public static void InitializeService(IDataServiceConfiguration config)
  {
    config.UseVerboseErrors = true;
    config.SetEntitySetAccessRule("Addresses", EntitySetRights.AllRead);
    config.SetServiceOperationAccessRule("GetAddresssByCity", ServiceOperationRights.All);
  }
}

Here, we have used IQueryable<T> interface so that the method can return an IQueryable collection of the type T, where T is a class. The [WebGet] attribute allows the method to be accessible in the HTTP GET operations. Also, the class attribute [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)] on the GenericCollections class will show the stack trace just in case you encounter any exceptions at the time of execution.

The following code snippet shows how you can query the data exposed by the data service:

protected void Page_Load(object sender, EventArgs e)
{
  System.Data.Services.Client.DataServiceContext dataServiceContext = new DataServiceContext(new Uri("http://localhost:2490/GenericCollections.svc"));
  IEnumerable<Address> addresses =dataServiceContext.Execute<Address>(new Uri("http://localhost:2490/GenericCollections.svc/Addresses"));
  var addressquery =from address in addresses
    where address.City.StartsWith("S")
    select address;

  foreach (var address in addressquery)
  {
    Response.Write(string.Format("{0}<BR/>{1}<BR/>{2}<BR/><BR/>", address.AddressID, address.AddressLine,address.City));
  }
}

LINQ to SQL allows you to create object models that map to the tables in the relational database. The object-relational mapping implementation of LINQ to SQL handles the execution strategy of the SQL queries. A database markup language file, also known as .dbml file, is generated by the Visual Studio IDE when you drag-and-drop database tables from the solution explorer on the LINQ to SQL design surface. When each table is dragged onto the design surface, a class is created for each table. These classes, known as entity classes, are partial classes. They contain a set of partial methods that allow adding custom implementations. The objects to entity classes are known as entities. Associations are automatically created by the LINQ to SQL designer based on the underlying table relationships.

The entity relationships between primary and foreign keys are automatically represented as object relationships by the LINQ to SQL component. The mapping scheme offered by LINQ to SQL provides less housekeeping tasks when tables and columns are changed in the relational database. Only the mapping rules need to be updated without changing the code in your application.

The AdventureWorksDataContext class (created using the LINQ to SQL Designer in Visual Studio 2012) looks like the following code:

[System.Data.Linq.Mapping.DatabaseAttribute(Name="AdventureWorks")]
public partial class AdventureWorksDataContext : System.Data.Linq.DataContext

Note

Note that it takes a DatabaseAttribute class that specifies the database name. This class also defines several overloaded constructors that can be used for appropriate reasons.

Advantages of LINQ to SQL

The basic advantages of LINQ to SQL over other ORM tools include:

  • Developing non-LINQ-to-SQL data-centric applications may consume significant time and effort in trying to build custom components that will interact with the data source. LINQ to SQL maps the tables to classes; this helps architects to design a better n-tier architecture, thus improving the productivity.
  • The properties in the entity classes are mapped to the columns in the table with the appropriate data type mapping scheme. Therefore, a compile time check is performed, reducing the runtime errors.
  • Another added benefit for the developers is the Intellisense that Visual Studio IDE provides while working with LINQ to SQL applications.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset