Further Exploration with LINQ - Page 1
       by Granville Barnett  |  24 September 2007

In my previous article, I looked at some of the core fundamentals of .NET 3.5 and C# 3.0, in particular we looked at LINQ to SQL using ad-hoc queries. In this article we will build on what we learnt and look at LINQ to SQL using stored procedures, and LINQ to XML; we will also demystify lambda expressions through a series of practical examples.

LINQ to SQL
One of the questions I often get asked when talking about LINQ to SQL is about how well it plays with stored procedures, after all not many companies or developers like to leave their database open to ad-hoc queries – we like to lock things down. The good news for anyone seriously looking at LINQ for use in their applications is that you can use stored procedures and still keep the flexibility offered by ad-hoc queries.

For all the examples in this article we will use the same database schema as the earlier article Next Generation Data Access with LINQ.

Configuring our Data Access Layer for Stored Procedures
We will use the SqlMetal tool again to generate our data access layer (DAL), however, this time we will look at how to hook up our DAL to use the stored procedures defined in our database. Setting up our data access layer for use with stored procedures is unbelievably easy using LINQ to SQL, even if you decided not to use the SqlMetal tool

The following snippet shows the definition for a stored procedure GetAuthors:

[StoredProcedure(Name="GetAuthors")]
public StoredProcedureResult<GetAuthorsResult> GetAuthors() {
return this.ExecuteStoredProcedure
<GetAuthorsResult>(((MethodInfo)(MethodInfo.GetCurrentMethod())));
}

One of the things to note is that when using SqlMetal to extract stored procedures from our database, the tool actually generates what looks like an entity for that stored procedure result:

public partial class GetAuthorsResult {
private int _AuthorId;
private string _AuthorName;
public GetAuthorsResult() {
}
 
[Column(Name="AuthorId", Storage="_AuthorId",
DBType="Int")]
public int AuthorId {
get {
return this._AuthorId;
}
set {
if ((this._AuthorId != value)) {
this._AuthorId = value;
}
}
}
 
[Column(Name="AuthorName", Storage="_AuthorName",
DBType="NVarChar(50)")]
public string AuthorName {
get {
return this._AuthorName;
}
set {
if ((this._AuthorName != value)) {
this._AuthorName = value;
}
}
}
}

The problem with this is that the GetAuthorsResult enumeration is actually identical to the entity Author already defined in the data access layer. There are a few ways around this, of which the simplest has been demonstrated excellently by Mike Taulty of Microsoft UK in one of his blog posts.

Note: Remember this is still a very early CTP of LINQ, so it’s likely that the final code generation tool will take into account the similarities between already defined entities and stored procedures.

Running a Few Queries
With our data access layer embracing the use of stored procedures, it’s time to run through some example queries to prove just how easy it is to use LINQ to SQL, and the flexibility it maintains in comparison to ad-hoc queries. Just like any custom DAL where you would map rows of data to user-defined entity types and expose them as a series of methods – we achieve the same effect here; however, the LINQ to SQL implementation is backed up with all the great new language enhancements introduced in C# 3.0 like anonymous types.

To retrieve all authors use:

BookShop db = new BookShop(_conn);
foreach (var author in db.GetAuthors()) {
Console.WriteLine(author.AuthorName);
}

Just as I explained in the previous article there will be many times when you want to specifically choose what properties you want access to, and maybe you even want to filter the objects in a way that is not defined in the stored procedure – this is all possible when using stored procedures in LINQ to SQL.

For example, the following shows you how to use the GetAuthors stored procedure in conjunction with a query:

var query = from a in db.GetAuthors()
            orderby a.AuthorName
            select new { a.AuthorName };
foreach (var book in query) {
Console.WriteLine(book.AuthorName);
}

Notice that stored procedures can be debugged in the usual way – see below image:

Figure 1

[ Debugging ]

When extracting the stored procedures from your database, all stored procedures that take any arguments will be taken into account when SqlMetal generates the methods associated with those stored procedures. In our scenario we have a stored procedure called GetAuthorByBookId, which takes a single parameter of type int – this leads to the generation of a method of the same name, which also takes a parameter of type int. If you have a stored procedure that takes n arguments then you will also have generated a method with the same n arguments.

For example:

//...
myDataContext.GetAuthorByBookId(8);
//...

In the next page, let's continue by looking at some other LINQ operations that we did not get to cover in this page.

Onwards to the next page.

1 | 2 | 3 | 4




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.