Todd Anglin's Code Campground

A casual look at the world .NET coding

September 2007 - Posts

Developer's Journal: It can happen to you

RRoD I am generally one of those people that hear people complain about a bad experience with a product and disregard it as one person's bad luck. When people lecture "it could happen to you", I think "Yeah right. I guess it could happen to me. But it never will." You can call me an optimistic skeptic. And for most of my life (thankfully) my skepticism has won out. My iPhone activated fine, my computers never get viruses, and I've never even seen a tornado in Texas. All that started to change this weekend, though, when I met face-to-face one problem I thought would never happen to me: the RRoD.

RRoD, or Red Ring of Death for uninitiated, is the Xbox 360's terminal message. When your Xbox presents you with these three red lights, your console's game playing days are done. Now I've seen all of the reports across the Internet about Xbox owners getting this error and even started to believe the reports that this may be a big problem for the 360. I even remember remarking to myself after a recent episode of the "Windows Weekly" podcast with Paul Thurrott- in which Paul says 7 of his 10 gaming buddies have had the RRoD- that getting the RRoD seems more like when not if it's going to happen. Even my own brother- who will be joining Microsoft in Redmond soon- had to deal with the RRoD this summer. The evidence of this being a major problem was staring me right in the face and I still figured it wouldn't happen to me.

I was wrong. After a long day of working around the house on Saturday, I retreated to my game room and fired up my 360 for a little Call of Duty 4 Beta before dinner. When the normal 360 loading screen didn't show up on my TV, I looked at my Xbox to make sure I turned it on. Much to my shock and dismay, staring back at me was the infamous RRoD I'd read about. It had finally happened to me.

Now, of course, Microsoft has extended the warranty and my Xbox is covered. Soon after the RRoD I ordered the repair service online so that I can ship my Xbox off this week for repairs and hopefully get it back in a few weeks. BUT, this is the biggest week in Xbox gaming of the year! Halo 3 is unleashed on the world Monday night and I was looking forward to "finishing the fight" with my brother and some friends online. What am I to do? Miss the fun and excitement of the Halo 3 launch courtesy of the most untimely RRoD?

No! A quick trip to Best Buy and $350 later I was back in business with an HDMI enabled Xbox. Of course, that action required a fair amount of begging to the wife and a solemn promise that I'd sell my original Xbox when it returned from its Microsoft surgery. So if anybody is looking for a freshly repaired Xbox, look me up in a few weeks.

What's the moral of this tragic story? If we look past the pitifully insignificant nature of the problem, I think we can extract two good lessons from this adventure:

  1. If you don't think it can happen to you, it can. Coming directly from someone who didn't think "it" (it could be anything) could happen to them until it did, I know this will do nothing to change those of you reading this that believe it can't happen to you. But when it does, write your own blog post and make sure you say I told you so.
  2. If you're planning on playing Halo 3 this Tuesday, make sure you've already made your deals to secure a backup 360. Unless you've already been through the RRoD, there's a good chance you'll need the backup.

Now if you'll excuse me, I need to go make sure I know where to hide if a tornado comes my way this week.

Using the LinqDataSource: A practical look

One of the new controls coming in the .NET 3.5/Visual Studio 2008 releases later this year is the LinqDataSource. Much has already been written about this new control, and by most accounts this is going to be a very cool addition to the ASP.NET framework. I don't think anyone could aspire to write more about using the LinqDataSource than Scott Guthrie did on his blog, so if you're looking for in-depth LinqDataSource 101 start there. Instead, today I'll present the answers to a few of the questions I had when I first started using the control and condense some of the information you can find across the 'Nets into one (hopefully) easy to read blog post.

What is the LinqDataSource control?

As fellow blogger and DeKlarit cheif software architect Andres Aguiar put it, the LinqDataSource control really should be called the LinqToSqlDataSource control. Among the new features in Visual Studio 2008 is an integrated O/RM (object-relational mapping) tool called LinqToSql. If you are familiar with O/RM tools, LinqToSql is simply Microsoft's flavor of O/RM that is based heavily on the new Linq data querying language. If you're not familiar, the easiest way to describe LinqToSql is a tool that automatically creates objects (or classes) in your code based on the database you point it at. This LinqToSql data mapping is central to the LinqDataSource's functionality, thus the suggested "LinqToSqlDataSource" rename.

Beyond that nuance, the LinqDataSource is like most other data source controls. You can easily point data bound controls (that support declarative binding) to a LinqDataSource via their DataSourceID property and they'll bind to the data just like they do with SqlDataSource or ObjectDataSource controls. The real power of the LinqDataSource lies in the LinqToSql data mapping (supplied via the ContextTypeName property) that "knows" a lot about your data source (unlike the Sql and Object data source controls). That makes the data source control significantly smarter than its predecessors, enabling paging, sorting, and data editing "out of the box" without writing any extra code.

How do I use the LinqDataSource control?

I should note at this point that the LinqToSql tools are new in Visual Studio 2008, so if you want to use the new data source control you'll need the beta for now and then an upgrade when VS 2008 ships.

To begin using the LinqDataSource, you need to start by creating a LinqToSql data context. The data context lives in your application's App_Code directory and usually has the ".dbml" file extension. You can manually create a data context by adding a new "LINQ to SQL Class" to your application and then drag and drop tables from the Server Explorer onto the context diagram. For a complete review of that process, Mr.Guthrie has once again provided a thorough blog post.

Once your data context is built, drag and drop a LinqDataSource on to your page from the Visual Studio Toolbox. Configure your LinqDataSource to point to your data context and then use the LinqDataSource SmartTag to define the data you want to select. A simple LinqDataSource might look something like this:

<asp:LinqDataSource ID="LinqDataSource1" runat="server" 
   ContextTypeName="ForumsDataContext"
   TableName="Posts"
   Select="new (postContent, dateCreated, fd_thread, aspnet_User)"
   OrderBy="dateCreated">
</asp:LinqDataSource>

You can see that I've specified a data context called "ForumDataContext" (this code is based off of the data model used in my "Build your own ASP.NET Forums in 60 minutes" web cast, if you're interested in the meaning of the fields I'm referencing). I've set the "TableName" property to the name of a table within my context, specifically "Posts". I then set a Select statement that defines the new objects with fields from my database that I want to display in my data bound control (which in this case will be a RadGrid from Telerik).

When this code runs, the LinqDataSource automatically creates new dynamic classes with properties based on my select statement and then binds them to my data control. The "auto" classes are named "DynamicClassX", where "X" is a number starting at 1 and incrementing as necessary to handle multiple LinqDataSources. You should never need to interact with these dynamic classes, but it is good to know how .NET handles Linq selects when you're debugging.

Finally, I can use my configured LinqDataSource by setting my Grid's DataSourceID property, like this:

<radG:RadGrid ID="RadGrid1" runat="server"
   AllowSorting="True"
   AllowPaging="True"
   PageSize="5" Width="480px"
   DataSourceID="LinqDataSource1"
   AutoGenerateColumns="true">
</radG:RadGrid>

Producing results like this:

linqDbStep1

How do I display values from related tables?

The last example looks good, but where did my "fd_thread" and "aspnet_User" values go? As it turns out, those "values" in my select statement represent objects (or in database terms, tables) related to the table "Posts". To display those values, I need to manually configure TemplateColumns in my Grid, like this:

<radG:GridTemplateColumn HeaderText="Thread" SortExpression="fd_thread.subject">
   <ItemTemplate>
      <asp:Label ID="Label3" runat="server" Text='<%# Eval("fd_thread.subject") %>'>
      </asp:Label>
   </ItemTemplate>
</radG:GridTemplateColumn>
<radG:GridTemplateColumn HeaderText="Username" SortExpression="aspnet_User.Username"> 
   <ItemTemplate> 
      <asp:Label ID="Label4" runat="server" Text='<%# Eval("aspnet_User.Username") %>'>
      </asp:Label>
   </ItemTemplate>
</radG:GridTemplateColumn>

By referencing the properties (in database terms, fields or columns) of these related objects, I can easily display the relational data in my Grid. Furthermore, any property in the related objects is available to me to display in my Grid at this point. I don't have to rewrite my query if I decide later that I want to display (let's say) the "LoweredUsername" field from the aspnet_User table. This flexibility is definitely one of the cooler aspects of LinqToSql and the LinqDataSource. In any event, the addition of my template columns enables me to display all of my data nicely in the Grid:

linqDbStep2 

Do I need to optimize my Linq queries?

Generally speaking, no. LinqToSql by default operates in a "lazy load" mode, which means data is only queried from your DB when it is actually used in your code. In most cases this is a good behavior that prevents your application from loading unnecessary data, but there are times when you don't want to use lazy loading. I'll examine some of the performance optimization techniques in future blog posts, but in the mean time you can check out a good series of posts on the topic created by C# MVP David Hayden.

For now, let's just look at the SQL statements generated by Linq to handle my select clause. Using SQL Server Profiler, we see that Linq generated and executed three SQL statements to load our grid on the first page load:

SELECT [t0].[postContent], [t0].[dateCreated], [t1].[threadId], [t1].[topicId],
   [t1].[subject], [t1].[dateCreated] AS [dateCreated2], [t2].[ApplicationId], 
   [t2].[UserId], [t2].[UserName], [t2].[LoweredUserName], 
   [t2].[MobileAlias], [t2].[IsAnonymous], [t2].[LastActivityDate] 
FROM [dbo].[fd_posts] AS [t0] 
   INNER JOIN [dbo].[fd_threads] AS [t1] ON [t1].[threadId] = [t0].[threadId] 
   INNER JOIN [dbo].[aspnet_Users] AS [t2] ON [t2].[UserId] = [t0].[userId] 
ORDER BY [t0].[dateCreated]

SELECT COUNT(*) AS [value] 
FROM [dbo].[fd_posts] AS [t0] 
   INNER JOIN [dbo].[fd_threads] AS [t1] ON [t1].[threadId] = [t0].[threadId] 
   INNER JOIN [dbo].[aspnet_Users] AS [t2] ON [t2].[UserId] = [t0].[userId]

SELECT TOP 5 [t0].[postContent], [t0].[dateCreated], [t1]. [threadId], [t1].[topicId], 
   [t1].[subject], [t1].[dateCreated] AS [dateCreated2], [t2].[ApplicationId], 
   [t2].[UserId], [t2].[UserName], [t2].[LoweredUserName], 
   [t2].[MobileAlias], [t2].[IsAnonymous], [t2].[LastActivityDate] 
FROM [dbo].[fd_posts] AS [t0] 
   INNER JOIN [dbo].[fd_threads] AS [t1] ON [t1].[threadId] = [t0].[threadId] 
   INNER JOIN [dbo].[aspnet_Users] AS [t2] ON [t2].[UserId] = [t0].[userId] 
ORDER BY [t0].[dateCreated]

Whenever we page our RadGrid- forwards or backwards- Linq only executes one query:

exec sp_executesql N'SELECT TOP 5 [t3].[postContent], [t3].[dateCreated], 
   [t3].[threadId], [t3].[topicId], [t3].[subject], [t3].[dateCreated2], 
   [t3].[ApplicationId],[t3].[UserId],[t3].[UserName], [t3].[LoweredUserName], 
   [t3].[MobileAlias], [t3].[IsAnonymous], [t3].[LastActivityDate] 
FROM ( SELECT ROW_NUMBER() OVER (ORDER BY [t0].[dateCreated]) AS [ROW_NUMBER], 
   [t0].[postContent], [t0].[dateCreated], [t1].[threadId], [t1].[topicId], 
   [t1].[subject], [t1].[dateCreated] AS [dateCreated2], [t2].[ApplicationId], 
   [t2].[UserId], [t2].[UserName], [t2].[LoweredUserName], [t2].[MobileAlias], 
   [t2].[IsAnonymous], [t2].[LastActivityDate] 
FROM [dbo].[fd_posts] AS [t0] 
   INNER JOIN [dbo].[fd_threads] AS [t1] ON [t1].[threadId] = [t0].[threadId] 
   INNER JOIN [dbo].[aspnet_Users] AS [t2] ON [t2].[UserId] = [t0].[userId] ) AS [t3] 
WHERE [t3].[ROW_NUMBER] > @p0 
ORDER BY [t3].[dateCreated]',N'@p0 int',@p0=5

We won't dive in to how these queries are generated or how to optimize them in this post, but the point is to see that at the end of the day LinqToSql is generating standard- and relatively efficient- SQL statements to pull your data out the database. In a future post, I'll show you how we can avoid executing unnecessary queries and avoid selecting unnecessary data.

Should I be impressed?

If you've ever spent much time creating data driven applications in ASP.NET, then you know how monotonous the process of creating data access code can become. Even if you use advanced data helper classes, you're still left dealing with ambiguous table and column names in your code. LinqToSql and the LinqDataSource bring a whole new level of productivity to Visual Studio and are sure to make data driven applications easier than ever to build. Sure O/RM is nothing new, but as with anything that gets direct integration with Visual Studio (eh..hem...unit testing) it makes the lives of many developers easier.

So yes, you should be impressed.

Developer's Journal: Cinema Displays are not for developers

KvmConfused I don't usually spend time blogging "personal stories", but I feel this story has a few lessons that will benefit all developers. Let me set the scene and see if it sounds familiar: Like most programming geeks, I have more than one computer at my desk. One is a powerful, easy to upgrade custom built desktop PC connected to a beautiful 23" Apple Cinema Display; the other is a top of the line ThinkPad T60. I love both machines, but I tend to only use my desktop for occasional gaming (though Bioshock and soon Halo 3 make that even more occasional) and I end up using my ThinkPad for all of my work (including this very post). That means I spend 50+ hours a week staring at a 15" screen using a travel sized mouse when there is a giant 23" Cinema Display behind me connected to a PC with countless "top of the line" peripherals.

That made me stop and say to myself, "Self- if you have a huge screen sitting behind you, why don't you spend more time using it?!" "That's a good idea," I thought. "Surely I can run to my local Fry's Electronics and find a KVM switch to solve my problem and then develop in bliss." That was one of my last positive thoughts for the day.

As it turns out, connecting a VGA equipped ThinkPad to a DVI Cinema Display is not an easy cheap task. If you go to your local big box electronics store, you're probably going to find a slew of KVM switches equipped with DVI, VGA, USB and (yes) PS/2. "PS/2?" you say. "Do they even include those ports on computers these days?" Apparently they do, and KVM manufactures are still spitting out switches that primarily cater to VGA and PS/2 setups. If you wade through the sea of Iogear devices, though, you'll find a few on the shelves equipped for DVI. But there's a catch. Almost all retail KVM switches limit DVI connections to 1600 x 1200 max resolutions. How many power users looking for a KVM switch with DVI really have a monitor with a max resolution of 1600 x 1200? Not this one.

To connect your VGA source to your already expensive Cinema Display, you're left with a couple of equally expensive options:

  1. If your laptop maker produces a docking station for your machine that provides a DVI-D connection (and the "-D" is important- digital DVI is required for the Cinema Display to work), buy it. For a couple hundred dollars, that will be your cheapest option. You can then connect your laptop directly to the Cinema Display or to a DVI KVM switch.
  2. If that's not available (or if you're not dealing with a laptop), you're going to have to buy a VGA to DVI-D converter. Expect to spend upwards of $250 for that pleasure. The $10 adapters at Fry's will not solve your problem. Adapters will pass through DVI-A (or analog) signal, which will not work with the Cinema Display.

Once you've found a way to get your VGA traveling in digital DVI format, you now need a high-end DVI KVM switch to handle the resolutions of the Cinema Display. Don't waste your time with the Iogear and Belkin brands in the stores- I've tried them all and returned them all. They do not work with the Cinema Display. Instead, look for a Gefen or Avocent KVM switch online to handle your WUXGA (1920 x 1200) resolutions. It'll set you back another couple hundred dollars, but that's life with the Cinema Display.

So let's total it up. To use your 23" Cinema Display with your VGA equipped laptop, first you'll drop about $900 on the monitor, then $250 on the docking station, then $200 on the KVM switch, for a grand total of $1350. For half that, you can buy a Dell 24" monitor that comes with DVI and VGA connectors. And thus my conclusion: Cinema Displays are not for developers. They may be pretty on your desk, but they're not nearly flexible enough to handle the demands of your average .NET developer.

Welcome to the Code Campground

Howdy! And welcome to the Code Campground. Many of you may already be readers of my Telerik focused blog, TelerikWatch.com, and if so, extra thanks and welcome to you. For everyone else, my name is Todd Anglin and I'm a Telerik Technical Evangelist and very active member of the .NET community. I have been a passionate ASP developer for years (back to the days of classic ASP) and a huge proponent of .NET since its introduction. I am honored to have been given the opportunity to blog on the official ASP.NET blogs and I am committed to making this a valuable feed to add to your readers.

What is the Code Campground blog all about? Primarily this blog will bring you original content and commentary on all things .NET- from ASP.NET to Silverlight. There will be full code samples, how-to articles, and commentary on the latest .NET news from Microsoft. This will not be just another "link blog" that continually points you to someone else's work. What you find here (for the most part) will not be anywhere else on the web.

Why "Code Campground"? If you have ever been camping, then you know the experience is usually simultaneously relaxing and engaging. As you relax and enjoy the great outdoors (something programmers should definitely do from time to time), tasks that would typically be considered work (like cooking, making a fire, etc.) suddenly become fun. And that's exactly how programming with .NET should be. When you code with .NET, the "work" should be fun- a laughable concept for most other programming languages. If you're not having fun coding with .NET, subscribe to this blog and let me share tips and tricks with you that are bound to make your life easier and make your coding fun again.

With the introductions out of the way, this blog will now assume its regular role. I hope you enjoy this new .NET resource and share your feedback once the content starts to flow. Since I maintain a couple of other blogs, don't expect extremely frequent posting here. I'll shoot for at least 5 - 6 posts a month, but they'll be good, original, content-full posts. Welcome to Camp!

More Posts