Archive for the ‘LINQ’ Category

LINQ to SQL and tables with no Primary Key

Friday, July 24th, 2009

I ran into an interesting issue with LINQ to SQL yesterday. I had to update a table with no Primary Key. As I expected, LINQ to SQL wasn’t too happy with this scenario. Unfortunately LINQ to SQL will only throw an exception when you try to Insert or Delete a record with no primary key. Updates fail silently.

It’s actually quite obvious when you look into what is happening. To do an update you would usually do something like this:

var update = (from v in db.SimpleRecords
              where v.identifier == 12
              select v).First();
update.value = "new value";
db.SubmitChanges();

Of course, nothing happens. Here’s the code (slightly edited for readability) that is generated by the LINQ to SQL classes:

[Table(Name="dbo.SimpleRecord")]
public partial class SimpleRecord
{
   private int _identifier;

   private string _value;

      public SimpleTable()
      {
      }

      [Column(Storage="_identifier", AutoSync=AutoSync.Always,
         DbType="Int NOT NULL IDENTITY", IsDbGenerated=true)]
      public int identifier
      {
         get
         {
            return this._identifier;
         }
         set
         {
            if (this._identifier != value)
            {
               this._identifier = value;
            }
         }
      }

      [Column(Storage="_value", DbType="VarChar(50)")]
      public string value
      {
         get
         {
            return this._value;
         }
         set
         {
            if (this._value != value)
            {
               this._value = value;
            }
         }
      }
}

Without a primary key the two following interfaces aren’t emitted: INotifyPropertyChanging and INotifyPropertyChanged

Therefore LINQ to SQL doesn’t know that your record has changed (so can’t warn you that it can’t update).

Now that you understand the problem the solution is simple: Define a primary key in your table.

LINQ Talk from Queensland MSDN User Group

Thursday, May 7th, 2009

Last month I did a talk on LINQ at the Queensland MSDN User Group. For your viewing pleasure the talk is available on Live Meeting. Check it out here:

LINQ: Powerful Stuff (QMSDNUG)

You may need to skip the first 5 minutes.

Slides are available here: http://linq.i-think22.net/LinqApril2009.pdf

Demos will be available soon.

Writing XML with XElement

Friday, February 27th, 2009

In my last post we looked at how you can use LINQ to XML and XElement to parse XML. But what if you want to create XML files programmatically? Or modify an existing XML document?

Let’s start by looking at how we might add a new entry to our blog. Here is the XML file again:

<?xml version="1.0" encoding="UTF-8"?>
<Blog>
   <Entries>
      <Entry Archived="false">
         <Title>My First Post</Title>
         <Body>I love LINQ. It's the best</Body>
         <Comments>
            <!-- TODO: Shouldn't comments have authors? -->
            <Comment>I love LINQ more</Comment>
            <Comment>LINQ is the way of the future.</Comment>
         </Comments>
      </Entry>
   </Entries>
</Blog>

So we want to add a new Entry under the Entries element. We’ll also assume that our XML file has been parsed into an XElement variable blog.

We’ll start by creating our entry first:

var entry = new XElement("Entry");
entry.SetAttributeValue("Archived", false);
entry.Add(new XElement("Title", "My Second Post"));
entry.Add(new XElement("Body", "Just a quick post."));
entry.Add(new XElement("Comments"));

We started by creating the element, set the “Archived” attribute, then added the other necessary elements. I’ve still added the Comments element even though it will be empty. Depending on the rules that have been set about how I should layout the XML it might be optional.

To check that my code worked I plugged it into LINQPad and dumped the value of entry like so:

entry.ToString().Dump();

The results showed me the following:

<Entry Archived="false">
   <Title>My Second Post</Title>
   <Body>Just a quick post.</Body>
   <Comments />
</Entry>

Wow, that’s exactly what we want. Even though we used a Boolean value instead of a String for the attribute, XElement was smart enough to display its value as a human readable string. The XML is also nicely formatted and readable. I added the call to ToString() to emphasise that it wasn’t LINQPad that was responsible for the improved formatting.

What we have done here is generate an XML fragment. Sometimes it is easier to think of large XML files as smaller fragments that can be handled independently.

So now all we have to do is find the Entries element and add our entry XElement to it like so.

blog.Element("Entries").Add(entry);

This will leave us with the final XML looking like this:

<Blog>
   <Entries>
     <Entry Archived="false">
       <Title>My First Post</Title>
       <Body>I love LINQ. It's the best</Body>
       <Comments>
         <!-- TODO: Shouldn't comments have authors? -->
         <Comment>I love LINQ more</Comment>
         <Comment>LINQ is the way of the future.</Comment>
       </Comments>
     </Entry>
     <Entry Archived="false">
       <Title>My Second Post</Title>
       <Body>Just a quick post.</Body>
       <Comments />
     </Entry>
   </Entries>
</Blog>

What about our XML declaration?

You might be wondering why the ToString() method of XElement doesn’t include the XML declaration. Because XElement represents a fragment of XML which could appear anywhere in an XML document. If it included the XML declaration it would lose this flexibility. However there is a workaround if you are outputting to a final file.

var blogDump = new StringBuilder();
blog.Save(new StringWriter(blogDump));

The Save() method on XElement automatically adds an appropriate XML declaration, which is probably a good idea as it sorts out the complicated things like the encoding and XML version (which I’ve never seen as anything other than 1.0 to date). The Save() method can take either the name of a file (as a String), an XmlWriter or TextWriter. In the example above I’ve used a StringWriter (which is a subclass of TextWriter) to save XML to a StringBuilder object which I could then use to build a string containing the XML. Save() also takes a second parameter, SaveOptions which allows you to save your XML file without the extra whitespace that I’ve shown above. If you want to save those bytes it might be worth looking at this option.

Where do we go from here?

I haven’t yet decided what my next LINQ post will cover (although LINQ to Entities is high on the agenda), so I won’t promise anything here now. I have much more to say still about LINQ, so feel free to post in the comments suggestions for areas to cover in future posts and the areas you would like to see covered in more detail. So far this has been fairly introductory and we’ll be building towards more advanced topics over the coming weeks.

XML Made Easy with LINQ to XML

Wednesday, February 25th, 2009

XML is a fantastic way to structure information. Here are the two things I like most about XML.

  1. It’s fundamental concepts are simple, making many XML files readable by regular humans.
  2. The formalised structure enables re-use of a more generalised XML parser.

Projects can certainly suffer from too much XML or XML is used when a better option exists. Once your XML files become too difficult to read in a text editor it may be better to look at another option (or better design your XML schema).

A lightning fast introduction to XML

Skip this section if you already know XML, but take time to look at this XML sample as it will be used throughout the article.

<?xml version="1.0" encoding="UTF-8"?>
<Blog>
   <Entries>
      <Entry Archived="false">
         <Title>My First Post</Title>
         <Body>I love LINQ. It's the best</Body>
         <Comments>
            <!-- TODO: Shouldn't comments have authors? -->
            <Comment>I love LINQ more</Comment>
            <Comment>LINQ is the way of the future.</Comment>
         </Comments>
      </Entry>
   </Entries>
</Blog>

Above is an example of a simple XML file. XML files follow a structured pattern called a schema. The schema defines the rules for what is allowed where and generally defines the structure of your file. Fortunately you don’t need to write a formal schema to get started with XML. Instead you can just start laying out your data. That’s where the “X” in XML comes from, because it is eXtensible.

So the sample XML above is being used to store the contents of a simple blog. XML isn’t the best way to do this, but a blog is a simple well understood concept. If you read my article on LINQ to SQL you might notice that this is very similar to the database example I used there.

Every XML document should start with what is known as an XML declaration. It’s in the first line of the XML and defines the version of the XML as well as the encoding of the file. If you are using notepad you can select the encoding when you save the file. The topic of encodings is out of the scope of this article.

The next important element that all XML files need is a root node. In this example our root node is called “Blog” and it holds all of our other elements. There can only be one root node in an XML document so if we wanted another blog we would have to put it in another XML file or redesign our XML to have a new root node (such as BlogCollection).

From there we can see that our XML document is made up of two key parts, elements and attributes. Elements are the things in angle brackets (called tags) and an element continues until it is closed with a matching closing tag. Closing tags are different from regular tags as they have a forward slash (/) before the name of the tag. We will use the term element to describe everything from the opening tag (a regular tag) to the closing tag, and a tag as the bit with the angle brackets.

There is also a special kind of tag called a self-closing tag that is both an opening tag and a closing tag. These tags have a forward slash before the closing angle bracket. For example:

<SelfClosingTag />

The space before the forward slash is optional (and stems back to compatibility with HTML). Personally I like keeping the space there, but your project may have different rules.

The other important concept is attributes. Attributes go inside the tag to provide more information about a tag. Attributes can only be used once per element (but one element can have multiple attributes). In the example above, we have given the entry tag the Archived attribute.

Sometimes it can be difficult to determine whether data should be expressed as an attribute or as a child element (an element inside another element). Typically the rule of thumb is that an attribute should be describing metadata, that is extra information about the element itself and how it might be interpreted. Occasionally this doesn’t clear things up at all. If you are still confused, consider the complexity of the data and whether multiple instances of the data will be required. Complex and repeating data is a sure sign that you want to use an element.

Importantly elements can contain other elements which can in turn contain more elements (and so on). XML follows a very strict hierarchy (which makes it easy to navigate) so an element must be closed inside the element that it was opened in. This means that any element (except the root node of course) has one and only one parent element. If you are modelling structured data it is unlikely you’ll run into troubles.

Finally I’ve also added a comment to remind me to add authors to the comments. We won’t actually be doing this, it was merely there to demonstrate how you can include comments in your XML documents. Comments should be ignored when parsing an XML file as they are unrelated to the data. Comments begin with <!-- and end with -->.

Ok, so by now you should know enough about XML to understand how we can parse this XML file and pull the necessary elements.

Now for the exciting stuff

LINQ to XML is a set of classes designed to work well with LINQ. It provides a very simple API that allows XML to be read and written with ease.

The centre of your LINQ to XML world is XElement. Through XElement we can access all of the important information in the sample above. Let’s start by writing a query that can help us get the Blog entries to display on the front page. We’ll assume I’ve loaded the XML as a string into a variable called blogXml.

var blog = XElement.Parse(blogXml);

var frontPage = from e in blog.Descendants("Entry")
                where e.Attribute("Archived").Value == "false"
                select e;

foreach (var entry in frontPage)
{
   WriteBlogTitle(entry.Element("Title").Value);
   WriteBlogBody(entry.Element("Body").Value);
   WriteBlogCommentCount(entry.Descendants("Comment").Count());
}

This example does absolutely no error checking (something you’ll definitely want to do if you are working with real XML) but demonstrates how simple it is to find particular elements inside XML. Additionally you can use XElement objects to pass XML fragments around your application. We could have made our LINQ query return an anonymous type that pulled out the Title, Body and Comment count for each entry, but instead we just pulled out the XElement itself. From there we were able count the comments inside our loop.

There is nothing preventing you from using these fantastic classes without having to use LINQ queries as well. In fact, most of the XML parsing code I’ve written lately doesn’t use LINQ queries at all to find elements, just the methods of the XElement class. Let’s look at the ones you’ll likely use most. Don’t worry that these parameters take an XName as their parameter, strings are automatically cast to a XName. You’ll need to use XName if you are dealing with namespaces (which I’ll discuss in a future post).

  • Element(XName name) returns the first immediate child element with the given name. If the element does not exist it returns null.
  • Elements() returns an IEnumerable<XElement> of all the immediate child elements. So against Blog the enumeration would yield a single “Entries” XElement. If there are no child elements the enumeration will be empty.
  • Elements(XName name) returns an IEnumerable<XElement> of all the immediate child elements with the given name. If no elements with the name exist it will return an empty enumeration.
  • Attribute(XName name) returns an XAttribute that is the attribute with the specified name. If the attribute does not exist it returns null.

To match the Element() and Elements() methods there are also a set of Descendant() and Descendants() methods. These work in the same way except that they return all elements under the node. We used this method when we were finding the Entry element as we didn’t care about the rest of the document’s hierarchy.

Because these methods return null if the element (or attribute) is not found it is important to check that the value is not null unless you are using a method which returns an IEnumerable<T> object.

Where to from here?

You now know all the important classes needed to parse XML files (perhaps to load up some strongly typed objects). In my next post I’ll be discussing how you can use this same class to build complex XML structures. In the meantime, check out the MSDN documentation for XElement.

An Introduction to LINQ to SQL

Tuesday, February 24th, 2009

So we already know that LINQ gives us a way to compose queries against IEnumerable<T> objects. LINQ to SQL gives us a way to describe our database so that we can use LINQ queries against the data and have LINQ to SQL generate the necessary SQL statements to get the results. With LINQ to SQL you can query, insert and delete data all with fully compiled LINQ queries. Although LINQ to SQL will take a back seat to the Entity Framework (I’ll cover that in a future post) according to the ADO.Net team blog’s “Update on LINQ to SQL and LINQ to Entities Roadmap“, LINQ to SQL remains a good simple way to set up a database.

I’ll just be covering the core concepts here. Each of these core concepts will still apply to LINQ to Entities although there are sure to be small differences.

Basic structure

In Visual Studio LINQ to SQL comes with a full designer experience. You’ll find “LINQ to SQL Classes” as an item under “Data” in the Add New Item dialog. Keep in mind that “DataContext” will be added to the end of the name you give. I’ve created many TestDataDataContext classes!

Once this item has been added you will be presented with a designer window. Assuming you are using a SQL Server or SQL Express database you can simply drag tables from the Server Explorer to the designer window (I’ll be discussing the tool sqlmetal.exe in a future post which can be used to get LINQ to SQL working with SQL Server Compact Edition). As you add more tables, the relationships will begin to appear. Dragging all these tables simply generates extra classes under the scenes. There are four important files that are part of the LINQ to SQL classes:

  • TestDataContext.dbml is the core file. It is an XML formatted file that describes the tables and relationships in your Data Context.
  • TestDataContext.dbml.layout is purely for the designer experience so that you can lay out your tables in a way that makes sense to you.
  • TestDataContext.designer.cs is where things get interesting. This is the file that contains all the classes that are generated from your .dbml file. These are partial classes so you can add extra methods and properties in a separate file.
  • TestDataContext.cs is the file where you put your extra methods and properties.

Each of the tables is represented as a class in your object model. The fields of the tables become the properties and relationships are also represented as properties. It is important to remember that the classes represent a single row from the database.

In addition to the classes representing your data model you also get a DataContext class (in this example TestDataContext) which you use to interact with your database. It has a property for each of your tables which are of type System.Data.Linq.Table<T> where T is the name of your class. So if you have a table of Users, you might call the class User (as it represents one user) and your DataContext would have a property Users of type System.Data.Linq.Table<User>.

Initialize your DataContext

All access to your data is done through the DataContext object. Before you can begin you’ll need to create an instance of the class. If you’ve used Visual Studio to connect to SQL Server or SQL Express database you probably have access to the default constructor which will use the connection string from your app.config file. If you’ve used sqlmetal.exe or if you want to manually specify a connection string you can use a simple constructor that just takes the connection string.

In the next examples, we’ll assume we have already initialized the data context using the connection string from app.config like so:

var db = new TestDataContext();

Query the database (SELECT)

Let’s start with a simple query to pull data from the database. Let’s say that we have a really simple blog with the following tables: Entries, Comments and Users. We’ll be using this same basic database through all of the following examples.

Let’s start with the front page. Because this is a simple blog all the posts will stay on the front page until we archive them. So we want to start by finding all the blog posts that haven’t been archived. Let’s start by looking at the raw SQL.

SELECT *
FROM Entries
WHERE e.Archived = 0

That’s a pretty simple query and in LINQ it is also simple:

var frontPage = from e in db.Entries
                where !e.Archived
                select e;

Again, this is just our query definition, this line of code will not execute the query against the database. To actually execute the query we need to do something like this:

foreach (var entry in frontPage)
{
   WriteBlogTitle(entry.Title);
   WriteBlogBody(entry.Body);
   // TODO: Show number of comments
}

Here WriteBlogTitle() and WriteBlogBody() methods are responsible for sending the output to the web browser. Both methods just take a string and are completely unaware of where the data is coming from.

I’ve included a TODO comment suggesting it might be good to show the number of comments for each entry. First I’ll show you how to do this by running an extra query for each entry:

foreach (var entry in frontPage)
{
   WriteBlogTitle(entry.Title);
   WriteBlogBody(entry.Body);
   WriteBlogCommentCount(entry.Comments.Count);
}

Because comments are associated with the entry we can directly access its count. This line will cause another database query so has obvious performance implications (as it needs to hit the database server for every single post). Instead we’ll rewrite the query so we pull everything we need from the database in one query.

var frontPage = from e in db.Entries
                where !e.Archived
                select new {
                              Entry = e,
                              CommentCount = e.Comments.Count
                           };

foreach (var post in frontPage)
{
   WriteBlogTitle(post.Entry.Title);
   WriteBlogBody(post.Entry.Body);
   WriteBlogCommentCount(post.CommentCount)
}

By creating a new anonymous type in the query we send one complex query to the database instead of lots of simple queries.

So what if a user actually wants to view those comments. This time we’ll accept that two database queries is acceptable (it’s a constant). So, let’s see how that might work for a page that displays a specific post.

var post = (from e in db.Entries
            where e.Id == id
            select e).FirstOrDefault();

if (post == null)
{
   // Post could not be found
   throw new ArgumentException();
}

WriteBlogTitle(post.Title);
WriteBlogBody(post.Body);

foreach (var comment in post.Comments)
{
   WriteBlogComment(comment.Comment);
}

It almost seems to easy to believe. Because the relationships are already defined LINQ to SQL is able to generate the second SQL statement to get each of the comments for that post. Most importantly we did all this without any strings!

Inserting data (INSERT)

Right now the blog is pretty boring, it can display posts and comments, but how do the posts and comments get there?  Let’s start with the simple example of creating a post.

var post = new Entry();

post.Title = "My first post";
post.Body = "I love LINQ. It's the best.";

db.Entries.InsertOnSubmit(post);
db.SubmitChanges();

That’s it. The post is now in the database. What about a comment?

var comment = new Comment();

comment.Comment = "I love LINQ more";
comment.Entry = post;

db.Comments.InsertOnSubmit(comment);
db.SubmitChanges();

We’ve been able to link the comment to the post by using the Entry property directly. We haven’t had to worry about how our tables are related in our code.

Deleting data (DELETE)

Did you get a spam comment on your blog? Don’t worry, LINQ to SQL can help you delete it. It follows a similar model to that of inserting data.

db.Comments.DeleteOnSubmit(comment);
db.SubmitChanges();

Updating data (UPDATE)

Maybe you want to start cleaning up the front page because it is starting to get cluttered. We need to update the Archived field on each of the entries we want to archive. To keep things really simple, we’ll archive all the posts that aren’t already archived.

var toArchive = from e in db.Entries
                where !e.Archived
                select e;

foreach (var entry in toArchive)
{
   entry.Archived = true;
}

db.SubmitChanges();

Remember to submit your changes

The key thing to remember when manipulating data with LINQ to SQL is to call SubmitChanges() on your DataContext object. Only then will the SQL statements be generated and executed on the server.

What’s next?

In my next LINQ post I’ll be exploring LINQ to XML.