Share your knowledge and create a knowledgebase.

Archive for the ‘.Net’ Category


DataContext class in depth : LINQ

Jul 30, 2008 Author: Ashish | Filed under: .Net

In this part of the series I will explain the DataContext class in depth through a series of examples and explanations.

Introduction

Whenever someone asks me about the DataContext I always refer to it as the “brains” of Linq to SQL, why? Because it is. It is responsible for the translation of Linq to T-SQL, and the mapping of the results (rows) of that query to objects, and so much more.

If you run any codegen tool (SqlMetal, or Linq to SQL file (VS Orcas designer)) you always get a class that derives from the DataContext class. The DataContext can be equated to a database, in that it contains a series of tables (normally this is implemented as a property that returns a Table), and sprocs (methods calls that invoke underlying sprocs at the DB layer).

Note: The DataContext can also handle other SQL Server features like views, and table functions etc.

What’s so special about the DataContext class?

Most notably the DataContext takes some Linq code and generates the appropriate T-SQL statement for that query; if that query returns rows then the DataContext object will take care of mapping those rows to objects.

Figure 5-1: DataContext core functionality

DataContextCorefunctionality DataContext class in depth : LINQ

I want to see the T-SQL generated by my LINQ

If you are a control freak/perfectionist like me then you probably want to know exactly what T-SQL is being generated for you at all times.

Before I show you some code please remember that the T-SQL generation by the DataContext object is not perfect, if you know of a very efficient T-SQL solution then implement that in a sproc. Saying that I have found the T-SQL generation of the DataContext object to be efficient in some advanced queries. Like so many things in programming one way, and one way alone is often not the best approach – experiment to see what offers the best performance for your query.

There are a few ways in which we can monitor the T-SQL being generated by our DataContext object, these include:

  • Visual Studio Orcas
  • ToString() override of query
  • DataContext Log property
  • SQL Server 2005 profiler (not included with Express edition)
Note: As the majority of people reading this article will be using the Express editions of the developer tools I will skip the SQL Server 2005 profiler demo. Those who have used the profiler before will know that it is a real time T-SQL dump of everything that a particular SQL Server 2005 instance is doing so seeing what T-SQL the DataContext is generating is a trivial task.

Visual Studio Orcas

As Linq is a 1st class citizen within the C# and VB.NET languages it should be no surprise to you whatsoever to see rich debugging support within the IDE.

Figure 5-2: Seeing the T-SQL generated by the DataContext object in VS Orcas

DataContextObjectInVSOrcas DataContext class in depth : LINQ

ToString() override

This is a really nice feature – if you call the ToString() method on any variable whose value is a query you can see the associated T-SQL for that query.

Figure 5-3: Calling ToString()

  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. namespace ConsoleApplication4
  5. {
  6. public class Program
  7. {
  8. public static void Main(string[] args)
  9. {
  10. using (BookShopDataContext db = new BookShopDataContext())
  11. {
  12. IEnumerable<Book> query = from b in db.Books select b;
  13. Console.WriteLine(query);
  14. }
  15. }
  16. }
  17. }

Figure 5-4: Result of running the code in Figure 5-3

5-4 DataContext class in depth : LINQ

Concurrency

Concurrency is always an issue – Linq to SQL by default uses optimistic concurrency. Take an example of where we retrieve a particular piece of data and then update that data, we then try to submit the updated data to the server but we get an exception as Linq to SQL knows that we have violated a concurrency check as we were acting upon “old” data.

Just to show this I did a pretty simple operation by adding a breakpoint on the line where I call the SubmitChanges(...) method and then executed some T-SQL code to alter that record and then continued the execution of my application so I would get an exception.

Figure 5-6: ChangeConflictException

ChangeConflictException DataContext class in depth : LINQ

The SubmitChanges(...) method is overrided to take a ConflictMode enum where we can change the default behaviour when data is submitted to the database, these are:

  • ContinueOnConflict
  • FailOnFirstConflict

The above can be used when within a TransactionScope. There are a few attribute values we can apply to our generated code to specifically say “we don’t care if this particular bit of data is changed – just overwrite it”. We do this using the UpdateCheck parameter to the Column attribute.

Figure 5-7: We don’t care about this data – just overwrite the value with what we have!

  1. [global::System.Data.Linq.Column(Storage="_Title", Name="Title",
  2. DBType="NVarChar(50) NOT NULL", CanBeNull=false,
  3. UpdateCheck=System.Data.Linq.UpdateCheck.Never)]

The UpdateCheck enum values:

  • Always
  • Never
  • WhenChanged

I’m pretty sure I’ve not covered everything in Linq to SQL with regards to concurrency – remember though that you can use the TransactionScope type in the .NET framework to assist you.

Using VS Orcas to look at data

Remember – queries only execute when we call the GetEnumerator() of the variable that holds the query! In previous CTP’s of VS Orcas it was hard to see what data we pulled back from the database as the debugger didn’t call the GetEnumerator() method when you wanted to look at that particular variable – the March CTP does however which is really great!

Let’s go ahead and look at using VS Orcas to look at data returned from our database using the Locals window when debugging. First place a breakpoint after the line you define a query, you don’t need a foreach to call the GetEnumerator() – the IDE will do that for us. When you get to your breakpoint you will see a screen similar to that in Figure 5-8 where the variable holding our query has a message saying something like “expand me to enumerate this IEnumerable”.

Figure 5-8: Thinking about enumerating the IEnumerable

EnumeratingIEnumerable DataContext class in depth : LINQ

Expand the results! You know you want to.

Figure 5-9: Viewing the results

5-9 DataContext class in depth : LINQ

You can see that in Figure 5-9 I have two objects returned from my query, I can drill down into the values of their properties and so forth.

On the face of it this is a pretty basic enhancement to the IDE, and you would be right in thinking so – but this is a great visual tool which I’m sure you will love when using Linq to SQL!

LINQ to SQL FAQ

Will LINQ to SQL support Oracle?

This is a common question, the answer to which is no. Linq to SQL is a lightweight O/R mapper targeted for use with SQL Server 2000/2005. For a more powerful O/R mapper look at the Entity Data Model (EDM) – EDM will support Oracle and other 3rd party databases.

I hate codegen tools, how much code does it really take to hook up to my DB using LINQ to SQL?

Surprisingly little, essentially you need to create a property with the correct access (get, set, or both?) with the appropriate Column attribute. The class with your properties should be pluralized and use the Table attribute to map it to the corresponding table in the database.

Finally you will need to create a class that derives from DataContext. In this class you will want to expose some properties that return a generic Table.

Below is the code for the TodoListDataContext and Task types:

Task.cs (type that is associated with records in Tasks):

  1. using System;
  2. using System.Data.Linq;
  3. namespace ConsoleApplication5
  4. {
  5. [Table(Name="Tasks")]
  6. public class Task
  7. {
  8. private int _taskId;
  9. [Column(Name = "TaskID", Storage = "_taskId",
  10. IsDBGenerated = true, IsPrimaryKey = true,
  11. CanBeNull = false, DBType = "int not null identity")]
  12. public int TaskID
  13. {
  14. get { return _taskId; }
  15. }
  16. [Column(Name = "Title", CanBeNull = false,
  17. DBType = "nvarchar(50) not null")]
  18. public string Title
  19. {
  20. get;
  21. set;
  22. }
  23. [Column(Name = "Complete", CanBeNull = false)]
  24. public bool Complete
  25. {
  26. get;
  27. set;
  28. }
  29. }
  30. }

TodoListDataContext.cs (type that exposes a Table of type Task, and defines connection string)

  1. using System;
  2. using System.Data.Linq;
  3. namespace ConsoleApplication5
  4. {
  5. public class TodoListDataContext : DataContext
  6. {
  7. public TodoListDataContext(string conn) : base(conn)
  8. {
  9. }
  10. public Table<Task> Tasks
  11. {
  12. get { return GetTable<Task>(); }
  13. }
  14. }
  15. }

Why are the changes to my data in SQL Server not being persisted?

Remember, in order to persist changes to SQL Server you need to call the SubmitChanges(...) method on your DataContext object after you have made changes to any data.

Can I use XML to define the O/R mapping?

Yes. You can use SqlMetal to generate an XML mapping file, when creating a DataContext you need to specify that your mapping is defined in an XML file by using the XmlMappingSource type.

I’m hitting the database every time for two identical queries, can I prevent this?

To prevent hitting the database every time you can load the results into memory (e.g. Append ToList() to a query) any subsequent calls to that query will use the in-memory collection rather than going off and querying the database again.

Is it possible to create code from XML?

Yes. You can create a .dbml file using SqlMetal and then generate a codefile (either VB.NET or CS) based on the XML defined in the .dbml.

What’s this deferred loading stuff?

Linq to SQL uses deferred loading when accessing properties of a related entity. Given a simple select query returning all Books, if I then want the publisher for each book then I can do so, however, behind the scenes the DataContext is doing a select where query to get the publisher for the current book. This is deferred loading.

Note: You can disable deferred loading using the EnableDeferredLoading property of a DataContext object.

Developing 3 tier application in CSharp using LINQ

Jul 30, 2008 Author: Ashish | Filed under: .Net

The ASP.NET application that we will create we be a 3 tier application, consisting of a data access layer (DAL), a business logic layer (BLL) and a presentation layer (PL).

We will be using Visual Studio Orcas Beta 1 for this tutorial.

Defining our database schema

Before we jump into coding some C# or ASP.NET we need to setup our database, more importantly we first need a database! If you haven’t already go and grab yourself a copy of SQL Express 2005. I will be using SQL Server Management Studio 2005 to create and define my database; however, you can do all of this using Visual Studio 2005 if you want.

Creating a database

Let’s go ahead and create a database for this tutorial. I’m going to create a database called TodoList. To create a database right click the Databases folder in the Object Explorer window and click New Database (Figure 4-1).

Figure 4-1: Creating a database

CreatingADatabase_Xlinq4 Developing 3 tier application in CSharp using LINQ

When the New Database window is visible enter TodoList (or any other name you want to use) as the Database name (Figure 4-2).

Figure 4-2: Specifying the database name

Specifyingthedatabasename_XLinq4 Developing 3 tier application in CSharp using LINQ

Adding the Tasks table

With our database created we will now add a Tasks table. In SQL Server Management Studio right click the Tables folder and select New Table (Figure 4-3).

Figure 4-3: Creating the Tasks table

CreatingTheTasksTable_Xlinq4 Developing 3 tier application in CSharp using LINQ

In the table designer replicate the settings from Figure 4-4.

Figure 4-4: Defining the columns

DefiningTheColumns_Xlinq4 Developing 3 tier application in CSharp using LINQ

Note: In Figure 4-4 TaskID is a primary key and identity.

When you save the table, save it as Tasks (Figure 4-5).

Figure 4-5: Saving the table

SavingTheTable_Xlinq4 Developing 3 tier application in CSharp using LINQ

Creating the stored procedures

We need to define three stored procedures, one for adding a new task, one for updating the state of a task, and finally one for retrieving all tasks of a specific state (either active, or closed).

Creating a stored procedure is easy, simply right click on the Stored Procedures folder and click New Stored Procedure (Figure 4-6).

Figure 4-6: Creating a stored procedure

CreatingStoredProcedure_Xlinq4 Developing 3 tier application in CSharp using LINQ

Below are the three code listings for the stored procedures we will use.

Figure 4-7: AddTask

  1. create procedure AddTask
  2. @Title nvarchar(50),
  3. @Complete bit
  4. as
  5. insert into Tasks (Title, Complete)
  6. values (@Title, @Complete)

Figure 4-8: GetTasksByState

  1. create procedure GetTasksByState
  2. @Complete bit
  3. as
  4. select TaskID, Title, Complete
  5. from Tasks
  6. where Complete = @Complete
  7. order by Title

Figure 4-9: UpdateTaskState

  1. create procedure UpdateTaskState
  2. @TaskID int,
  3. @Complete bit
  4. as
  5. update Tasks
  6. set Complete = @Complete
  7. where TaskID = @TaskID

Setting up our data access layer

With our database ready let’s go ahead and create our DAL. We will use the LINQ to SQL file designer in Visual Studio Orcas to do this.

Note: You will first need to add a connection to the TodoList database in the Server Explorer window.

Right click on your website project and add a new LINQ to SQL file called TodoList (Figure 4-10).

Figure 4-10: Adding a LINQ to SQL file to our project

AddingLINQToSQL_Xlinq4 Developing 3 tier application in CSharp using LINQ

With the file created drag and drop the Tasks table and the three stored procedures we created on to the design canvas of the designer (Figure 4-11).

Figure 4-11: Adding our table and sprocs to our DAL

AddingTableTSprocs_Xlinq4 Developing 3 tier application in CSharp using LINQ

That’s it! Our DAL is all ready to use.

Adding a business logic layer

In this tutorial there is not much point to adding a BLL, but we will add one nonetheless.

This layer in a real life application this layer would enforce any business rules (parameter checking etc…). Also in a real life application you would want to separate your DAL and BLL into their own components.

Right click the App_Code folder and add a new class called TasksBll.cs, then copy and paste the class definition given in Figure 4-12 into that file.

Figure 4-12: TasksBll.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Org.GBarnett.Dns
  5. {
  6. public static class TasksBll
  7. {
  8. /// <summary>
  9. /// Gets all tasks of a particular state
  10. /// </summary>
  11. public static List<GetTasksByState> GetTasksByState()
  12. {
  13. using (TodoListDataContext db = new TodoListDataContext())
  14. {
  15. return (from t in db.GetTasksByState() select t).ToList<GetTasksByState>();
  16. }
  17. }
  18. /// <summary>
  19. /// Adds a new task
  20. /// </summary>
  21. public static void AddTask(string title, bool complete)
  22. {
  23. using (TodoListDataContext db = new TodoListDataContext())
  24. {
  25. db.AddTask(title, complete);
  26. }
  27. }
  28. /// <summary>
  29. /// Updates a tasks state
  30. /// </summary>
  31. public static void UpdateTaskState(int taskId, bool complete)
  32. {
  33. using (TodoListDataContext db = new TodoListDataContext())
  34. {
  35. db.UpdateTaskState(taskId, complete);
  36. }
  37. }
  38. }
  39. }

Each method of the TasksBll.cs (Figure 4-12) performs the appropriate operation by accessing methods defined in our DAL.

Enter ASP.NET…

As previously mentioned we will use ASP.NET to define the UI.

The UI will consist of 3 controls:

  • DropDownList
  • GridView
  • FormView

Before we begin add a new AJAX Web Form to your project, the name you give it is irrelevant. Add all the following code snippets inside the form tag of the page.

We have two states

Either a task is active or complete. We will use a drop down list control to store these values (Figure 4-12).

Figure 4-13: DropDownList containing the tasks states

  1. <asp:DropDownList ID=“ddlState” runat=“server” AutoPostBack=“true”>
  2. <asp:ListItem Selected=“True” Text=“Active” Value=“false” />
  3. <asp:ListItem Text=“Complete” Value=“true” />
  4. </asp:DropDownList>

Adding an ObjectDataSource

Before we add any more controls to our web page we need to hook our presentation layer up with our BLL. To do this we will add an ObjectDataSource and wire it up to the appropriate methods defined in our BLL.

Figure 4-14: Adding an ObjectDataSource

  1. <asp:ObjectDataSource
  2. ID=“odsTasks”
  3. runat=“server”
  4. TypeName=“TasksBll”
  5. SelectMethod=“GetTasksByState”
  6. InsertMethod=“AddTask”
  7. UpdateMethod=“UpdateTaskState”>
  8. <SelectParameters>
  9. <asp:ControlParameter
  10. ControlID=“ddlState”
  11. Name=“complete”
  12. PropertyName=“SelectedValue”
  13. Type=“Boolean” />
  14. </SelectParameters>
  15. <UpdateParameters>
  16. <asp:Parameter Name=“taskId” Type=“int32″ />
  17. <asp:Parameter Name=“complete” Type=“boolean” />
  18. </UpdateParameters>
  19. <InsertParameters>
  20. <asp:Parameter Name=“title” Type=“string” />
  21. <asp:Parameter Name=“complete” Type=“boolean” />
  22. </InsertParameters>
  23. </asp:ObjectDataSource>

Using a GridView to view the tasks

We will now go ahead and add a GridView to our page (Figure 4-15).

Note: I have customized the Item and Edit templates for the checkbox control.

Figure 4-15: Adding a GridView to our page to display the tasks

  1. <asp:GridView
  2. ID=“gvTasks”
  3. runat=“server”
  4. DataSourceID=“odsTasks”
  5. AutoGenerateColumns=“false”
  6. DataKeyNames=“TaskID”
  7. AllowPaging=“true”
  8. GridLines=“None”
  9. AlternatingRowStyle-CssClass=“alternate”>
  10. <Columns>
  11. <asp:BoundField DataField=“Title” HeaderText=“Task” ReadOnly=“true” />
  12. <asp:TemplateField HeaderText=“Complete”>
  13. <ItemTemplate>
  14. <asp:CheckBox ID=“cbI” runat=“server” Checked=‘<%# Eval(”Complete”) %>’
  15. Enabled=“false” />
  16. </ItemTemplate>
  17. <EditItemTemplate>
  18. <asp:CheckBox ID=“cbE” runat=“server” Checked=‘<%# Bind(”Complete”) %>’ />
  19. </EditItemTemplate>
  20. </asp:TemplateField>
  21. <asp:CommandField ShowEditButton=“true” />
  22. </Columns>
  23. </asp:GridView>

Using the FormView to add more tasks

To add a new task we will use a FormView (Figure 4-16).

Note: I have not included any data input checking to keep the example as simple as possible.

Figure 4-16: Adding a FormView to allow the user to add new tasks

  1. <asp:FormView ID=“fvTask” runat=“server” DefaultMode=“Insert” DataSourceID=“odsTasks”>
  2. <InsertItemTemplate>
  3. <p><strong>Title:</strong>
  4. <asp:TextBox ID=“txtTitle” runat=“server” Text=‘<%# Bind(”Title”) %>’ /></p>
  5. <p><strong>Complete:</strong>
  6. <asp:CheckBox ID=“cbC” runat=“server” Checked=‘<%# Bind(”Complete”) %>’ /></p>
  7. <p><asp:LinkButton ID=“lbAdd” runat=“server” Text=“Add Task” CommandName=“Insert” /></p>
  8. </InsertItemTemplate>
  9. </asp:FormView>

Adding AJAX functionality to the GridView and the FormView controls

Just to smooth things up I’ve added a few UpdatePanel’s to the page, each wrapping the GridView and FormView respectively.

Figure 4-17: The updated GridView

  1. <asp:UpdatePanel ID=“upTasks” runat=“server”>
  2. <ContentTemplate>
  3. <asp:GridView
  4. ID=“gvTasks”
  5. runat=“server”
  6. DataSourceID=“odsTasks”
  7. AutoGenerateColumns=“false”
  8. DataKeyNames=“TaskID”
  9. AllowPaging=“true”
  10. GridLines=“None”
  11. AlternatingRowStyle-CssClass=“alternate”>
  12. <Columns>
  13. <asp:BoundField DataField=“Title” HeaderText=“Task” ReadOnly=“true” />
  14. <asp:TemplateField HeaderText=“Complete”>
  15. <ItemTemplate>
  16. <asp:CheckBox ID=“cbI”
  17. runat=“server”
  18. Checked=‘<%# Eval(”Complete”) %>’
  19. Enabled=“false” />
  20. </ItemTemplate>
  21. <EditItemTemplate>
  22. <asp:CheckBox ID=“cbE” runat=“server” Checked=‘<%# Bind(”Complete”) %>’ />
  23. </EditItemTemplate>
  24. </asp:TemplateField>
  25. <asp:CommandField ShowEditButton=“true” />
  26. </Columns>
  27. </asp:GridView>
  28. </ContentTemplate>
  29. <Triggers>
  30. <asp:AsyncPostBackTrigger ControlID=“ddlState” />
  31. </Triggers>
  32. </asp:UpdatePanel>

Figure 4-18: The update FormView

  1. <asp:UpdatePanel ID=“upAdd” runat=“server”>
  2. <ContentTemplate>
  3. <asp:FormView ID=“fvTask” runat=“server” DefaultMode=“Insert” DataSourceID=“odsTasks”>
  4. <InsertItemTemplate>
  5. <p><strong>Title:</strong>
  6. <asp:TextBox ID=“txtTitle” runat=“server” Text=‘<%# Bind(”Title”) %>’ /></p>
  7. <p><strong>Complete:</strong>
  8. <asp:CheckBox ID=“cbC” runat=“server” Checked=‘<%# Bind(”Complete”) %>’ /></p>
  9. <p>
  10. <asp:LinkButton ID=“lbAdd” runat=“server” Text=“Add Task” CommandName=“Insert” />
  11. </p>
  12. </InsertItemTemplate>
  13. </asp:FormView>
  14. </ContentTemplate>
  15. </asp:UpdatePanel>

And on that note we are finished! You can download the full source code at the end of this tutorial.

The experience

From personal experience coding the data access layer can be a very boring process – in this tutorial we have seen how effective LINQ to SQL can be when creating our DAL.

Visual Studio Orcas has introduced a few really cool tools to further assist with the creation of the DAL – we no longer need to spend hours on OR mapping. The great thing about LINQ is the ability to further query your DAL, and create some anonymous type.

There is no doubt in my mind that LINQ is set to revolutionize the way programmers interact with data, more so is the fact that we always use a familiar set of standard query operators!

If you download and run the source you will see the site shown in Figure 4-19.

Figure 4-19: Our to-do list web site

ToDoList_Xlinq4 Developing 3 tier application in CSharp using LINQ

Entities and Key Types in application using Linq

Jul 30, 2008 Author: Ashish | Filed under: .Net

In this part we will look a little more at what entities are, as well as taking a closer look at the key types we can use and their application.

Entities?

When we talk about entities we are generally talking about a more functional representation of our schema. A perfect view of this is the Visual Studio Orcas LINQ to SQL file designer (Figure 3-1). If you drag a few tables onto the design surface you will see an abstract view of your database schema showing only the entity names and the relationships between the entities.

Figure 3-1: Entities in Visual Studio Orcas

EntitiesVisualStudioOrcas Entities and Key Types in application using Linq

Essentially when we talk about entities in LINQ to SQL we are more or less talking about our applications view of the data - our entities don’t necessarily need to map to tables in our database.

Go ahead and drag a few tables onto the designer.

If you take a look at the code generated for you by the designer you will see several attributes that map the particular class (entity) to a table in the database (Figure 3-2). You will also see that the properties are associated with columns in the classes associated table (Figure 3-3). An interesting thing to note is that there is not a direct mapping between CLR and SQL Server types so these attributes take care of the relevant plumbing to map the types accordingly.

Figure 3-2: Associating a class with a table

  1. [System.Data.Linq.Table(Name="dbo.Books")]
  2. public partial class Book { //…

Figure 3-4: Associating a property with a column in a table

  1. [System.Data.Linq.Column(Storage="_BookID",
  2. Name="BookID",
  3. DBType="Int NOT NULL IDENTITY",
  4. IsPrimaryKey=true,
  5. IsDBGenerated=true,
  6. CanBeNull=false)]

Inspecting the DataContext class

The DataContext class is the most important class when using LINQ to SQL. If you have inspected the code generated for you by the LINQ to SQL File designer then you will notice that the partial class derives from the System.Data.Linq.DataContext class.

In a nutshell the DataContext is in charge of generating the SQL statement from your language query, and then mapping the rows of data (if any) returned from your database to objects. The DataContext is indeed a very interesting class (we will revisit this class throughout this series!).

If we construct a simple query (Figure 3-4) we can inspect the SQL that the DataContext generates for us (Figure 3-5).

Figure 3-4: Simple query

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Linq;
  5. namespace IntroToLinq
  6. {
  7. public class Program
  8. {
  9. public static void Main()
  10. {
  11. using (BookShopDataContext db = new BookShopDataContext())
  12. {
  13. IEnumerable<Book> books = from b in db.Books select b;
  14. foreach (Book b in books)
  15. {
  16. Console.WriteLine(b.Title);
  17. }
  18. }
  19. }
  20. }
  21. }

Figure 3-5: SQL generated by the DataContext object for Figure 3-4

SQLGeneratedDataContext Entities and Key Types in application using Linq

If a class implements IDisposable then make good use of it!! By wrapping our BookShopDataContext object in a using statement we implicitly call the Dispose() method for this object. Calling Dispose() releases any resources held by our object. If you don’t want to use the using statement call the objects Dispose() method explicitly within a finally block.

I’m not going to cover all of the great things that the DataContext class offers to us – we will do that in subsequent parts. Stay tuned!

Stored Procedures

Let’s take a look at using stored procedures in LINQ to SQL. Up until now we have been composing ad-hoc queries in C#. I like to code my SQL queries as sprocs in the database layer and then invoke those sprocs via my apps DAL – this is a very, very common approach.

First thing we will do is create a simple sproc that simply returns all the names of the publishers, Figure 3-6 shows this.

Figure 3-6: Selecting all the names of the publishers

  1. create procedure GetPublishers
  2. as
  3. select PublisherID, PublisherName
  4. from Publishers
  5. order by PublisherName

I like to use Microsoft SQL Server Management Studio 2005 to code all my SQL. If you want you can do this in Visual Studio, however, there are some great features in Management Studio like being able to view the execution plan.

If you run this query you will get all the names of the publishers in the database as shown in Figure 3-7.

Figure 3-7: Result of executing sproc defined in Figure 3-6

ResultOfExecutingSproc Entities and Key Types in application using Linq

With our sproc defined in our database we will go back into Visual Studio and drag the stored procedure from the server explorer window onto the designer canvas of the LINQ to SQL File (Figure 3-8).

Figure 3-8: Dragging the GetPublishers sproc onto the design canvas

DraggingGetPublishersSproc Entities and Key Types in application using Linq

When you have dragged your sproc onto the canvas you will see that the designer generates a method of the same name. There is a method pane on the designer that allows you to see all methods in your DAL (dragging a sproc onto the designer generates a method that executes your sproc).

Figure 3-9: The method pane

TheMethodPane Entities and Key Types in application using Linq

I mentioned in the previous part of this series that we would be using a tool called SQLMetal in this part. I decided not to use that tool for now purely because the designer is a little more educational in that it creates a visual representation of your DAL. In the next part of this series where we create an application using LINQ to SQL we will use the SQLMetal.exe command line tool.

Using our GetPublishers() method

Before we use this method in our code let us first take some time to look at the code that the designer generated for us (Figure 3-10).

Figure 3-10: Generated code for GetPublishers()

  1. [global::System.Data.Linq.StoredProcedure(Name="dbo.GetPublishers")]
  2. public global::System.Collections.Generic.IEnumerable<GetPublisher>
  3. GetPublishers()
  4. {
  5. global::System.Data.Linq.Provider.IQueryResults<GetPublisher> result =
  6. this.ExecuteMethodCall<GetPublisher>(this,
  7. (
  8. (global::System.Reflection.MethodInfo)
  9. (global::System.Reflection.MethodInfo.GetCurrentMethod()))
  10. );
  11. return
  12. (
  13. (global::System.Collections.Generic.IEnumerable<GetPublisher>)
  14. (result)
  15. );
  16. }

The GetPublishers() method is decorated with a StoredProcedure attribute, this attribute associates this method with the appropriated sproc in our database. What we return is an enumeration of type GetPublisher (coincidentally this type looks exactly the same as Publisher – we will rectify this in a moment!). For now we will ignore the reflection stuff and the IQueryResults interface – we will cover those bits in a few parts time!

Before we move on we will use the GetPublishers() method in a query (Figure 3-11).

Figure 3-11: Composing a query using the GetPublishers() method

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Linq;
  5. namespace IntroToLinq
  6. {
  7. public class Program
  8. {
  9. public static void Main()
  10. {
  11. using (BookShopDataContext db = new BookShopDataContext())
  12. {
  13. var publishers = from p in db.GetPublishers() select p;
  14. foreach (GetPublisher publisher in publishers)
  15. {
  16. Console.WriteLine(“{0} {1}”,
  17. publisher.PublisherID,
  18. publisher.PublisherName);
  19. }
  20. }
  21. }
  22. }
  23. }

Hang on! What the GetPublishers() method returns is an enumeration of type GetPublisher! What the heck is that?! Good question! Well at the moment the designer is not smart enough to recognize that you are returning back an enumeration of type Publisher, which we already have defined! What we have at the moment are two types exactly the same! We will rectify this now.

  1. Go into the BookShop.designer.cs and delete the GetPublisher type.
  2. Replace all occurrences of GetPublisher in the GetPublishers method – this includes the method signature (return type), and a few other lines with Publisher.

Once you have completed the above steps your GetPublishers() method should look like that in Figure 3-12.

Figure 3-12: The new, slightly tweaked GetPublishers() method

  1. [global::System.Data.Linq.StoredProcedure(Name="dbo.GetPublishers")]
  2. public global::System.Collections.Generic.IEnumerable<Publisher>
  3. GetPublishers()
  4. {
  5. global::System.Data.Linq.Provider.IQueryResults<Publisher> result =
  6. this.ExecuteMethodCall<Publisher>
  7. (
  8. this,((global::System.Reflection.MethodInfo)
  9. (global::System.Reflection.MethodInfo.GetCurrentMethod()))
  10. );
  11. return ((global::System.Collections.Generic.IEnumerable<Publisher>)
  12. (result));
  13. }

You can now modify the code in Figure 3-11 to that shown in Figure 3-13.

Figure 3-13: A more elegantly named return type

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Linq;
  5. namespace IntroToLinq
  6. {
  7. public class Program
  8. {
  9. public static void Main()
  10. {
  11. using (BookShopDataContext db = new BookShopDataContext())
  12. {
  13. var publishers = from p in db.GetPublishers() select p;
  14. foreach (Publisher publisher in publishers)
  15. {
  16. Console.WriteLine(“{0} {1}”,
  17. publisher.PublisherID,
  18. publisher.PublisherName);
  19. }
  20. }
  21. }
  22. }
  23. }

Querying relational data using Linq

Jul 30, 2008 Author: Ashish | Filed under: .Net

This article is based on a single table schema (don’t worry subsequent parts will see a much more complex database schema!) so that you can get to grips with LINQ to SQL (the name for using LINQ with relational data – also known as DLINQ in a previous life, but we won’t go into that…) quickly and feel confident with this awesome new language enhancement.

Conceptual data access layer?

Conceptual what?! If you are familiar with the concept of a database schema then you don’t have much to worry about! You can think of a conceptual data access layer as being your applications view of the database.

I don’t want to bog you down with entities yet! That will come in part 3 of this series. Just know that what we deal with from our applications point of view is a series of entities describing the tables and relationships in our database schema. I will let you look forward to the diagrams explaining all of this in the next part!

Generating our DAL using Visual Studio Orcas

Typically DAL’s have consisted of boilerplate code to map relational data to objects and vice versa, speaking from experience I really enjoyed this the first time I did it – but now it just annoys the heck out of me! With that in mind it’s no surprise that the folks on the Visual Studio team decided to give us a few tools to generate that boilerplate code.

At present there are two tools that come with Visual Studio Orcas (both were in the LINQ May 2006 CTP):

  • SQLMetal.exe – a command line tool that gives you a tonne of options when creating your DAL. Things of note are pluralisation of entities, extracting stored procedures from your database schema, and defining the namespace, as well as a tonne of other stuff.
  • LINQ to SQL file – used to be called DLINQ objects in the LINQ May 2006 CTP, now it has a cooler name, but it’s pretty much the same tool. This is a file template that lives in Visual Studio Orcas – it’s a designer. Personally I don’t really like stuff that is “drag and drop” so I tend to opt for the finer control offered to me by SQLMetal – with that said it’s a bit of a shock to me that I have opted to use the designer for this part of the series.

Before we go any further I just want to give you a quick snapshot of the table that we will be using for this part of the series – like I mentioned earlier the next part will have several tables with many relationships…think of it as a throwaway schema (actually I don’t think if even qualifies as a database schema it’s so simple!).

Figure 2-1: Our unbelievably simple database schema (for now!)

Our unbelievably simple database schema (for now!)

I bet you are questioning my credibility now aren’t you?! Come on its simple so that you can learn the basics quick so when we look at more complex examples in the future you have a good solid understanding of using LINQ with relational data.

Ok, go ahead and add some dummy data to that table.

Fire up Visual Studio Orcas (the March 2007 CTP remember) and create a new .NET 3.5 Console Application. When you’ve done that right click the project and add a LINQ to SQL File – as all we’ll be throwing away all of the code in this part just name it Part2.dbml for now.

Figure 2-2: Adding a LINQ to SQL File to our solution

Adding a LINQ to SQL File to our solution

At this moment in time we have everything setup so drag the Books table from the server explorer window onto the canvas of Part2.dbml.

Figure 2-3: Result of dragging the Books table onto Part2.dbml

Result of dragging the Books table onto Part2.dbml

If you take a look at the code that has been generated for us you will notice there is a class called Book that implements a few interfaces (more on those in the next part). Take a look at the attribute that is placed before the class definition (fig. 2-4) here we are associating this type (Book) with Books table in our database.

Figure 2-4: Associating the Book type with our Books table

//…
[System.Data.Linq.Table(Name="dbo.Books")]
//…

Take a moment to look at the fields in the Book type – notice that the designer has created two fields of the same names as the columns in the Books table; properties have also been defined in the class marked with an attribute to associate the fields with their corresponding column in the Books table (Fig. 2-5).

Figure 2-5: Associating the fields in the Book type with the columns in our Books table

//…
[System.Data.Linq.Column(Storage="_BookId",
  Name="BookId",
  DBType="Int NOT NULL IDENTITY",
  IsPrimaryKey=true,
  IsDBGenerated=true,
  CanBeNull=false)]
//…
[System.Data.Linq.Column(Storage="_Title",
  Name="Title",
  DBType="NVarChar(50) NOT NULL",
  CanBeNull=false)]
//…

Before we move on we will talk a little about the Column attribute (defined in the System.Data.Linq namespace). Take a look at Fig. 2-5, notice that we explicity state the field that stores the value of the column, e.g. the BookId columns’ value is stored in the _BookId field, we also state that this property is associated with the BookId column in the Books table (Name="BookId").

If you are familiar with SQL Server data types then you will also know that there is not a 1..1 mapping between SQL Server 2005 data types and CLR types, e.g. the CLR has no money data type. For this reason we can explicitly state the database column type, the designer will choose the most appropriate type for use for that particular property, e.g. for the BookId column the designer has chosen to use the default int value type (Int32).

Before we move on, just be aware that you have to explicitly state what values are generated by the database, and whether or not they can be null. In the case of BookId the database generates a new integer automatically for each row; this column is also a primary key.

Take some time to further examine the Column and Table attributes.

Querying our DAL

We will now go through a few simple queries against the DAL that we have created in previous steps.

For each example I have provided the query version and the lambda expression version.

Select all books

Figure 2-6: Selecting all books (query)

using System;
using System.Linq;

namespace Org.GBarnett.Dns.Linq {
  public class Program {
    public static void Main() {
      Part2DataContext db = new Part2DataContext();
      var query = from b in db.Books select b;
      foreach (var book in query) {
        Console.WriteLine(“{0} {1}”, book.BookId, book.Title);
      }
    }
  }
}

Figure 2-7: Selecting all books (lambda expressions/extension methods)

using System;
using System.Linq;

namespace Org.GBarnett.Dns.Linq {
  public class Program {
    public static void Main() {
      Part2DataContext db = new Part2DataContext();
      var query = db.Books.Select(x => x);
      foreach (var book in query) {
        Console.WriteLine(“{0} {1}”, book.BookId, book.Title);
      }
    }
  }
}

I should note that in fig. 2-7 you can omit the Select extension method and you will achieve the same result as when including the Select extension method and its lambda expression parameter; however, the example code given is clearer than when omitting the Select extension method.

Select the titles of the books whose title length is greater than 6 characters

Figure 2-8: Selecting the titles of the books with length > 6 (query)

using System;
using System.Collections.Generic;
using System.Linq;

namespace Org.GBarnett.Dns.Linq {
  public class Program {
    public static void Main() {
      Part2DataContext db = new Part2DataContext();
      IEnumerable<string> query =
        from b in db.Books where b.Title.Length > 6 select b.Title;
      foreach (string title in query) {
        Console.WriteLine(“{0}”, title);
      }
    }
  }
}

Figure 2-9: Selecting the titles of the books with length > 6 (lambda expressions/extension methods)

using System;
using System.Collections.Generic;
using System.Linq;
namespace Org.GBarnett.Dns.Linq {
  public class Program {
    public static void Main() {
      Part2DataContext db = new Part2DataContext();
      IEnumerable<string> query =
        db.Books.Where(x => x.Title.Length > 6).Select(x => x.Title);
      foreach (string title in query) {
        Console.WriteLine(“{0}”, title);
      }
    }
  }
}

Introduction to Language Integrated Query: LINQ

Jul 30, 2008 Author: Ashish | Filed under: .Net

Language Integrated Query (LINQ, pronounced “link”) is a Microsoft .NET Framework component that adds native data querying capabilities to .NET languages using a syntax reminiscent of SQL. LINQ was released as a part of .NET Framework 3.5 on November 19, 2007.

LINQ defines a set of query operators that can be used to query, project and filter data in arrays, enumerable classes, XML, relational database, and third party data sources. While it allows any data source to be queried, it requires that the data be encapsulated as objects. So, if the data source does not natively store data as objects, the data must be mapped to the object domain. Queries written using the query operators are executed either by the LINQ query processing engine or, via an extension mechanism, handed over to LINQ providers which either implement a separate query processing engine or translate to a different format to be executed on a separate data store (such as on a database server as SQL queries). The results of a query are returned as a collection of in-memory objects that can be enumerated.

Standard Query Operators

The set of query operators defined by LINQ are exposed to the user as the Standard Query Operator API. The query operators supported by the API are:

Select / SelectMany Further information: Map (higher-order function)

The Select statement is used to perform a projection on the collection to select either all the data members that make up the object or a subset of it. The SelectMany operator is used to perform a one-to-many projection, i.e., if the objects in the collection contain another collection as a data member, SelectMany can be used to select the entire sub-collection. The user supplies a function, as a delegate, which selects the data members. The delegate is invoked on all the objects to project out the unneeded data members. Selection creates an object of a different type, which has either same or as many data members as the original class. The class must be already defined for the code to be compilable.

Where Further information: Filter (higher-order function)

The Where operator allows the definition of a set of predicate rules which are evaluated for each object in the collection, and objects which do not match the rule are filtered away. The predicate is supplied to the operator as a delegate.

Sum / Min / Max / Average / Aggregate Further information: Fold (higher-order function)

These operators take a predicate that retrieves a certain numeric value from each element in the collection and uses it to find the sum, minimum, maximum, average or aggregate values of all the elements in the collection, respectively.

Join / GroupJoin
The Join operator performs an inner join on two collections, based on matching keys for objects in each collection. It takes two functions as delegates, one for each collection, that it executes on each object in the collection to extract the key from the object. It also takes another delegate via which the user specifies which data elements, from the two matched elements, should be used to create the resultant object. The GroupJoin operator is used to perform a group join. Like the Select operator, the results of a join are instantiations of a different class, with all the data members of both the types of the source objects, or a subset of them.

Take / TakeWhile
The Take operator is used to select the first n objects from a collection, while the TakeWhile operator, which takes a predicate, selects those objects which match the predicate.

Skip / SkipWhile
The Skip and SkipWhile operators are complements of Take and TakeWhile - they skip the first n objects from a collection, or those objects which match a predicate (for the case of SkipWhile).

OfType
The OfType operator is used to select the elements of a certain type.

Concat
The Concat operator concatenates two collections.

OrderBy / ThenBy
The OrderBy operator is used to specify the primary sort ordering of the elements in a collection according to some key. The default ordering is in ascending order, to reverse the order the OrderByDescending operator is to be used. ThenBy and ThenByDescending specifies subsequent ordering of the elements. The function to extract the key value from the object is specified by the user as a delegate.

Reverse
The Reverse operator reverses a collection.

GroupBy
The GroupBy operator takes a delegate that extracts a key value and returns a collection of IGrouping<Key, Values> objects, for each distinct key value. The IGrouping objects can then be used to enumerate all the objects for a particular key value.

Distinct
The Distinct operator removes duplicate instances of a key value from a collection. The function to retrieve the key value is to be supplied as a delegate.

Union / Intersect / Except
These operators are used to perform a union, intersection and difference operation on two sequences, respectively.

EqualAll
The EqualAll operator checks if all elements in two collections are equal.

First / FirstOrDefault / Last / LastOrDefault

These operators take a predicate. The First operator returns the first element for which the predicate yields true or throws an exception if nothing matches. The FirstOrDefault operator is like the First operator except that it returns the default value for the element type (usually a null reference) in case nothing matches the predicate. The last operator retrieves the last element to match the predicate, or throws an exception in case nothing matches. The LastOrDefault returns the default element value if nothing matches.

Single
The Single operator takes a predicate and returns the element which matches the predicate. An exception is thrown if none or more than one elements match the predicate.

ElementAt
The ElementAt operator retrieves the element at a given index in the collection.

Any / All / Contains
The Any operator checks if there are any element in the collection matching the predicate. It does not select the element, but returns true for a match. The All operator checks if all elements match the predicate. The Contains operator checks if the collection contains a given value.

Count
The Count operator counts the number of elements in the given collection.

The Standard Query Operator also specifies certain operators which converts a collection into other types:

* AsEnumerable: converts the collection to IEnumerable<T> type.
* ToQueryable: converts the collection to IQueryable<T> type.
* ToArray: converts the collection to an array.
* ToList: converts the collection to IList<T> type.
* ToDictionary: converts the collection to IDictionary<T, K> type, indexed by the key K.
* ToLookup: converts the collection to ILookup<T, K> type, indexed by the key K.
* Cast: converts a non-generic IEnumerable collection to one of IEnumerable<T> by casting each element to type T. Throws an exception for incompatible types.
* OfType: converts a non-generic IEnumerable collection to one of IEnumerable<T>. Only elements of type T are included.

The query operators are defined in the IEnumerable<T> interface as generic extension methods, and a concrete implementation is provided in the Sequence class. As a result, any class which implements the IEnumerable<T> interface has access to these methods and are queryable. LINQ also defines a set of generic Func delegates, which define the type of delegates handled by the LINQ query methods. Any function wrapped in a Func delegate can be used by LINQ. Each of these methods return an IEnumerable<T>, so the output of one can be used as input to another, resulting in query composability. The functions, however, are lazily evaluated, i.e., the collections are enumerated only when the result is retrieved. The enumeration is halted as soon as a match is found, and the delegates evaluated on it. When a subsequent object in the resultant collection is retrieved, the enumeration of the source collection is continued beyond the element already evaluated. However, grouping operations, like GroupBy and OrderBy, as well as Sum, Min, Max, Average and Aggregate, require data from all elements in collection, and force an eager evaluation. LINQ does not feature a query optimizer and the query operators are evaluated in the order they are invoked. The LINQ methods are compilable in .NET Framework 2.0, as well.

Language Extensions

While LINQ is primarily implemented as a library for .NET Framework 2.0, it also defines a set of language extensions that can be optionally implemented by languages to make queries a first class language construct and provide syntactic sugar for writing queries. These language extensions have initially been implemented in C# 3.0, VB 9.0 and Chrome, with other languages like F# and Nemerle having announced preliminary support. The language extensions include:

* Query syntax: Languages are free to choose a query syntax, which it will recognize natively. These language keywords must be translated by the compiler to appropriate LINQ method calls. The languages can implement operator reordering and other optimizations at the keyword level.
* Implicitly typed variables: This enhancement allows variables to be declared without specifying their types. The languages C# 3.0 and Chrome declare them with the var keyword. In VB9.0, the use of the Dim keyword without type declaration accomplishes the same declaration. Such objects are still strongly typed; for these objects the compiler uses type inference to infer the type of the variables. This allows the result of the queries to be specified and their result defined without declaring the type of the intermediate variables.
* Anonymous types: Anonymous types allow classes, which contain only data member declarations, to be inferred by the compiler. This is useful for the Select and Join operators, whose result types may differ from the types of the original objects. The compiler uses type inference to determine the fields contained in the classes and generates accessors and mutators for these fields.
* Object Initializer: Object initializers allow an object to be created and initialized in a single scope, this allows creation of delegates that extract fields from an object, create a new object and assign the extracted data to the fields of the new object in a single statement, as is required for Select and Join operators.
* Lambda expressions: Lambda expressions are used to create delegates inline with other code. This allows the predicates and extraction functions to be written inline with the queries.

For example, in the query to select all the objects in a collection with SomeProperty less than 10,

int SomeValue = 5;

var results =  from c in SomeCollection
let x = SomeValue * 2
where c.SomeProperty < x
select new {c.SomeProperty, c.OtherProperty};

foreach (var result in results)
Console.WriteLine(result);

the types of variables result, c and results all are inferred by the compiler - assuming SomeCollection is IEnumerable<SomeClass>, c will be SomeClass, results will be IEnumerable<SomeOtherClass> and result will be SomeOtherClass, where SomeOtherClass will be a compiler generated class with only the SomeProperty and OtherProperty properties and their values set from the corresponding clauses of the source objects. The operators are then translated into method calls as:

IEnumerable<SomeOtherClass> results =
SomeCollection.Where
(
c => c.SomeProperty < (SomeValue * 2)
)
.Select
(
c => new {c.SomeProperty, c.OtherProperty}
)
foreach (SomeOtherClass result in results)
Console.WriteLine( result.ToString() );

LINQ Providers

LINQ also defines another interface, IQueryable<T>, which defines the same interfaces to the Standard Query Operators as IEnumerable<T>. However, the concrete implementation of the interface, instead of evaluating the query, converts the query expression, with all the operators and predicates, into an expression tree. The Expression tree preserves the high level structure of the query and can be examined at runtime. The type of the source collection defines which implementation will run - if the collection type implements IEnumerable<T>, it executes the local LINQ query execution engine and if it implements the IQueryable<T> implementation, it invokes the expression tree-based implementation. An extension method is also defined for IEnumerable<T> collections to be wrapped inside an IQueryable<T> collection, to force the latter implementation.

The expression trees are at the core of LINQ extensibility mechanism, by which LINQ can be adapted for any data source. The expression trees are handed over to LINQ Providers, which are data source-specific implementations that adapt the LINQ queries to be used with the data source. The LINQ Providers analyze the expression trees representing the query (”query trees”) and generate a DynamicMethod (which are methods generated at runtime) by using the reflection APIs to emit CIL code. These methods are executed when the query is run. LINQ comes with LINQ Providers for in-memory object collections, SQL Server databases, ADO.NET datasets and XML documents. These different providers define the different flavors of LINQ:

LINQ to Objects
The LINQ to Objects provider is used for querying in-memory collections, using the local query execution engine of LINQ. The code generated by this provider refer the implementations of the standard query operators as defined in the Sequence class and allows IEnumerable<T> collections to be queried locally.

LINQ to XML
The LINQ to XML provider converts an XML document to a collection of XElement objects, which are then queried against using the local execution engine that is provided as a part of the implementation of the standard query operator.

LINQ to SQL
The LINQ to SQL provider allows LINQ to be used to query SQL Server databases as well as SQL Server Compact databases. Since SQL Server data resides on a remote server, and because it already includes a querying engine, LINQ to SQL does not use the query engine of LINQ. Instead, it converts a LINQ query to SQL query which is then sent to SQL Server for processing. However, since SQL Server stores the data as relational data and LINQ works with data encapsulated in objects, the two representations must be mapped to one another. For this reason, LINQ to SQL also defines the mapping framework. The mapping is done by defining classes which corresponds to the tables in database, and containing all or a subset of the columns in the table as data members. The correspondence, along with other relational model attributes such as primary keys are specified using LINQ to SQL-defined attributes. For example,

[Table(Name="Customers")]
public class Customer
{
[Column(IsPrimaryKey = true)]
public int CustID;

[Column]
public string CustName;
}

this class definition maps to a table named Customers and the two data members correspond to two columns. The classes must be defined before LINQ to SQL can be used. Visual Studio 2008 includes a mapping designer which can be used to create the mapping between the data schemas in the object as well as relational domain. It can automatically create the corresponding classes from a database schema, as well as allow manual editing to create a different view by using only a subset of the tables or columns in a table.

The mapping is implemented by the DataContext which takes a connection string to the server, and can be used to generate a Table<T> where T is the type that the database table will be mapped to. The Table<T> encapsulates the data in the table, and implements the IQueryable<T> interface, so that the expression tree is created, which the LINQ to SQL provider handles. It converts the query into T-SQL and retrieves the result set from the database server. Since the processing happens at the database server, local methods, which are not defined as a part of the lambda expressions representing the predicates, cannot be used. However, it can use the stored procedures on the server. Any changes to the result set are tracked and can be submitted back to the database server.

LINQ to DataSets
The LINQ to SQL provider works only with Microsoft SQL Server databases; to support any generic database, LINQ also includes the LINQ to DataSets, which uses ADO.NET to handle the communication with the database. Once the data is in ADO.NET Datasets, LINQ to Datasets execute queries against these datasets.

Other providers
The LINQ providers can be implemented by third parties for various data sources as well. Several database server specific providers are available from the database vendors. Some of the popular providers include:

* Data Services: LINQ to ADO.NET Data Services
* Entity Framework: LINQ to Entities
* DbLinq: LINQ to MySQL, PostgreSQL, and Oracle
* Google search: LINQ to Google
* Windows Search: LINQ to System Search