www.codinghillbilly.com   kyle.baley.org  Subscribe / Contact
 
 
 
 
LATEST POSTS
Sunday, May 28, 2006

Code camp is done! Enjoyed myself immensely and even had a tinge of bittersweetness. I'm heading home in less than two weeks just as I'm starting to meet more and more interesting people.

Will post the code from my presentation shortly. In the meantime, just want to congratulate John Bristowe on his recent MVP status. Who knew he was such a master?

Friday, May 26, 2006
I'm all prepped for my presentation at this Saturday's Code Camp. If you're at all interested in client-side web development, you won't want to miss it. The app I'm presenting is cool enough but wait'll you see what Atlas can (and can't) do. You'd better come out or else I...ummm....won't see you there...I guess.
Friday, May 19, 2006

I generally consider myself a web developer. I work in ASP.NET, SharePoint, Content Management Server and the like. Been using AJAX features for years and have even done some Atlas stuff. So am I allowed to say that I don't use Firefox?

There's no real reason for it really. I'm just not dissatisfied enough with my IE experience to switch. Tabbed browsing to me seems like a serious step backwards. As I type this, I have six browser windows open along my taskbar. One for my gmail, one for my HSx account, two for an app I'm working on, etc, etc. I can tell all this because it says so right there on the task bar. If all of those websites are in various tabs, I lose all that and I have to go fishing for the window I want.

It's the same reason I rejoiced when Word stopped being an MDI (yes, it's still an MDI; you know what I mean). It's also why one of the first things I do to a new XP installation is to turn off “Group similar taskbar buttons” in my taskbar properties. And it's why I'll turn off tabbed browsing on IE 7 the minute I install it.

But back to Firefox. Like I said, I have nothing against the browser. I've tried it on and off since it came out (including version 1.0 PR which refuses to uninstall from my laptop). Last time, I think I remember it rendering things faster and I'm sure it does because everyone tells me it does. But IE's rendering time has never really struck me as being a problem. Then again, it's not something I generally pay attention to. Probably more accurate to say it's never been a problem I've noticed.

Some of the add-ins for Firefox look cool. I've tried a couple but didn't use them much after the initial love affair wore off. Same thing happens with portals for me. I try them for a bit, then stop when they don't fit in with my normal workflow. I use NewsGator to read my RSS feeds because I like that it integrates with Outlook. I can't get into opening a browser to do it. Just doesn't feel right to me.

In the end, I just don't care enough about browsers in general to make the switch. To me, it's just...well...a browser. For browsing. I don't care about the bells and whistles. I don't need it to aggregate my news. I don't need it to play music. I don't need it to remind me of the weather in Colorado every morning at 9:00. Yes, I build web apps and yes, I get excited about what you can do in a browser, especially with the likes of Atlas and Magic Ajax. I love the technology behind Flickr and del.icio.us. And I love building web apps that use it. Doesn't mean I use them myself.

Whenever I open my browser, it's to do something very specific. Run an app I'm building. Find a piece of code on Google Groups. Check out movie times. Do the crossword. These are atomic actions for me. I don't need to open a browser to some generic page and wait for the whole thing to load when all I want is one little corner of it. And I know I'm not the only one whose home page is about:blank.

So don't take this as a slight against Firefox or worse, as a vote for IE over Firefox. They're pretty much interchangeable for me. I use IE now because most of my clients want apps that target it. When more clients want Firefox apps, I'll switch. When Opera goes mainstream, I'll switch again. I just plain don't care as long as whatever browser I'm using doesn't get in my way.

What does interest me is that Firefox has spurred a nice little renaissance in browser development. At first I was kind of ticked that I had to go back to all my public websites and futz with them (don't whine to me about writing standards-compliant HTML; if IE's on 95% of computers, it is the standard). But now I'm pumped that some of these said standards might actually get supported. Especially the voice styles in CSS. Can't wait to build websites that talk to you.

But I'll never use one myself.

Monday, May 15, 2006

(No, I've never read the book. Just want to sound more cultured than I am. A hillbilly can dream, can't he?)

Been doing quite a bit of work with Atlas in preparation for the upcoming Calgary Code Camp. Part of it involves writing a traditional ASP.NET application and converting it to Atlas, a process that is mind-blowingly simple. Trust me, folks, there is no editting magic in the demos. Add a couple of <atlas:UpdatePanel> tags and a ScriptManager and you're done. I'll be demonstrating this approach live on May 27 so come check it out if you're in the area.

I don't generally question the inner workings of a new technology but I've always kind of liked what you can do with client-side scripting (which is what it was called in the olden days of the early 21st century; the acronym never really caught on for some reason). And since I'm going to purport to being an expert of some sort, I thought it best to dig behind the curtain a bit.

When I first started working with UpdatePanels, my first thought was, of course: how is it generating the UpdatePanels client-side given how little work is needed to do it? Given what I know about AJAX, my initial suspicion was pretty sobering. Here's what I thought would happen when you clicked an element that normally causes a postback:

  1. All form elements are gathered together
  2. An XMLHTTP object posts back to the given page passing in the form elements
  3. The resulting page is parsed and the HTML for the UpdatePanel is removed from its HTML and injected into the client-side page

The reason I thought this is that I couldn't see any other way of accomplishing this task. But if this was true, there is one pretty big concern: What are we gaining by switching to UpdatePanels? We are still posting all the form elements to a page and still generating the entire response. All we've done is add the overhead of parsing the page and injecting part of the response back into our client page. Sure it gets rid of screen flicker but that's only part of what makes client-side scripting so attractive.

Luckily, there are smarter people than I working on the Atlas project. Here's what really happens when you perform a "postback":

  1. All form elements are gathered together
  2. An XMLHTTP object posts back to the given page passing in the form elements
  3. The resulting page is parsed and the HTML for the UpdatePanel is removed from its HTML and injected into the client-side page

Yes, it's the same as the above list. The difference 'twixt the two is in the definition of "resulting page". In my original assumption, I thought that meant the entire page would get returned. But that doesn't appear to be the case. My first clue-in for this is that the response comes back as XML. I.E. It comes back in the responseXML object of the XMLHTTP, not the response object. The response contains only the HTML to be injected into each UpdatePanel along with some other necessary client-side script. That is, it doesn't return the entire page, only what has (potentially) changed.

I'm not really sure how they've accomplished this. I didn't change any of the server-side code so how does it know to generate a delta response rather than a full one? My guess is that an Atlas HTTP handler is doing some work behind the scenes. Atlas does add a bunch of things to the web.config and I'm only vaguely aware of the inner workings of HTTP handlers and HTTP modules. (But James Kovacs' ImposterHTTPModule does look pretty cool.)

In any case, this is not nearly as efficient as it could be. It generates a response for every UpdatePanel on the page regardless of whether it has changed or not.

At least, that's what it does by default. By judicious use of Mode="Conditional" on the UpdatePanel, you can tell the Atlas framework to update the region only on certain conditions. For example, on a button click or when the Update( ) method is explicitly called in the code-behind. In this way, you can have multiple UpdatePanels on the page, each updating only when it makes sense to do so. And your developers can take the blue pill and stay in their little ASP.NET world without having to learn what Atlas can really do.

It's very powerful and makes a better demo than the early DataSet and DataConnection demos from .NET 1.0 which were flashy but you'd never actually write an app that way (right?). UpdatePanels are easy to implement and you would actually use them in practice. But they are only a small part of the Atlas framework, which also includes an entire client-side library you can use to make the requests even more efficient (i.e. pass in and request only the data that you need and styling the results through DHTML or XSL or the declarative Atlas approach which I'm just getting into).

So you could take the low road and just add UpdatePanels throughout your app without linking them to other controls or adding any further code. I wouldn't necessarily recommend the approach for new Atlas applications but it is fantastic for a first step in converting existing applications to use more client-side code. It produces a very quick win for very little code. And in many cases, the extra data passed back and forth is likely negligible. If you've got a fast network connection, the extra data going back and forth is likely negligible and should be balanced against the cost of having a team of monkeys, er...highly skilled developers build it using the client-side library.

Caveat: Absolutely everything I've talked about here has been the result of my own research and I didn't exactly follow the scientific method. In other words, debugging Javascript is &%*^ hard. I'm not associated with Microsoft nor have I talked with anyone on the Atlas team to confirm or deny any of my assumptions. For all intents and purposes, Atlas "appears" to work as I've described but I will be the first to back down if someone questions anything I've said based on their own experimentation or discussions with people who know better.

Sunday, May 07, 2006

You'd think I have nothing better to do on a Saturday night. You'd think right...

I have attached, for your viewing pleasure, the settings file for my installation of Visual Studio 2005. Recently re-configured because uninstalling ReSharper left them in such a state and I had to reset and rebuild them. ReSharper did say something about backing up my settings but Jayzus knows where I put them.

Here's a summary of the changes:

  • Consolas font. Because I was told to. But at 11pt because 10pt seemed too small. Guess I'm getting old after all.
  • Display fifteen items in the Recent Projects list. Who works on less than six projects?
  • Solution Explorer, Server Explorer, and Properties Window docked along the left. I like them here because they are closer to the code I'm looking at. And when I debug, they are docked along the right so it's always obvious whether I'm debugging or not.
  • Spacing and formatting. Some years ago, a good friend and a developer I respect highly suggested the spacing scheme I currently use and I love it. In general, there are spaces within parentheses, both for function calls and in expressions. Casts are the exception so that they stand out as casts. I find this makes code much, much easier to read as does most extra whitespace in generally.

So export your own settings to back them up and check them out if you're curious and/or brave. Note that the formatting changes are for C# because at the moment, it's all I code in.

Sunday, May 07, 2006

Couple of short miscellaneous items to balance the tome I wrote last time:

  1. The Start Page in Visual Studio can be customised to show your own news feed rather than the default one. Go to Tools | Options | Environment | Startup. I'm also told you can use something like http://www.feedjumbler.com to collate a bunch of your feeds together into one which you can then use as the main feed for Visual Studio. I'm feeling “sign-up“ averse today so I haven't checked out Feed Jumbler
  2. You can also set the number of recent items that appear on the start page. Tools | Options | Environment | General and change “items shown in recently used lists“. Note that this also changes the number of items in File | Recent Files and File | Recent Projects.
  3. There appears to be no way of getting rid of the Getting Started and Headlines sections.
  4. Have been playing with the beta of ReSharper 2.0 and love it. Type “throw new“ and it displays only available exceptions. Reference a class with no corresponding “using“ statement at the top and it is added for you. Type “using“ at the top and it displays the full hierarchy of namespaces available, not just the current level. And I've only been using it for a day. But it is uninstalling as we speak. Granted, my laptop is two years old and showing its age, but there is a very noticeable drop in performance of Visual Studio 2005. Plus I got some unhandled exceptions when working in a SQL database in Server Explorer. Tried to submit the error to help the developer folks out but that required me to sign up for something. See point 1. Regardless, when I upgrade my hardware and when they're out of beta, I'll gladly hand over $150 for it (pending a review of Code Rush).
Tuesday, May 02, 2006

download the source code (292Kb)

In Part 1, we established how our search was going to perform and described a sample domain object with some properties we will use in our search criteria. Here, we'll talk about the SQL that we'll be using to generate our search results.

To that end, there is code attached with the first draft of our search engine. It is functional in that it will allow you to specify some search criteria and display the results. It is pretty in that it is not. I'm the Salieri of UI; I can recognize when it's done right but am average (at best) at building them. For this example, I chose not to try.

I haven't addressed any of the client-side improvements mentioned in part one. But the topic of this article will be at the other end, in the database. The search results will be expanded upon in a future article. For now, we're interesting only in getting results.

Final cop-out: I don't usually use SqlDataSource in my web apps. The exception is for samples and demos which, frankly, is the only reason I can think of to use them. Having said that, they rock for samples and demos.


Until relatively recently, I was under the impression that search queries had to be done using hard-coded SQL. There are two main reasons for this.

First is the multi-select listboxes and checkbox lists. With these, a user can select one or more items on which to filter. For example, let's say the user selects four different project types. That means, of course, he or she wants all Moos that have any of those project types attached.

In SQL, this translates to:

      SELECT      *
      FROM        Moo
      WHERE ProjectType IN ( 1, 2, 3, 4 )

It's the IN criteria that presents a problem. We can't pass in a comma-delimited list to replace ( 1, 2, 3, 4 ). SQL Server simply doesn't allow this. It won't throw an error if you do this but trust me on this, it just doesn't work.

The second issue has to do with the part of the search screen where you specify how to search for the name. I.E. The radio button list where you specify "Starts with", "Ends with", etc.

In this case, there's no getting around the fact that we're going to need some conditional logic. And in SQL, that means either an IF statement or a CASE statement.

But each of these would need to occur in the WHERE clause. For example:

          SELECT    *
          FROM      Moo
          WHERE

                   IF @searchMethod = 'startswith'
                       Moo.Name LIKE @name + '%'
                   ELSE IF @searchMethod = 'endswith'
                       Moo.Name LIKE '%' + @name
                   ELSE IF @searchMethod = 'isexactly'
                       Moo.Name = @name
                   ELSE IF @searchMethod = 'notspecified'
                       Moo.Name LIKE '%'

And so on and so forth. But this SQL is, of course, just plain wrong. I don't mean wrong in the philosophical sense. I mean in the "it won't compile" sense. The same is true for putting a CASE statement in the WHERE clause in a similar fashion.

Alternatively, you could use the IF statement as follows:

          IF @searchMethod = 'startswith'
                SELECT    *
                FROM      Moo
                WHERE     Moo.Name LIKE @name + '%'
          ELSE IF @searchMethod = 'endswith'
                SELECT    *
                FROM      Moo
                WHERE     Moo.Name LIKE '%' + @name

And so on and so forth. Granted this will work in this case but that's because of the lack of imagination I put into the example. There are other cases where a conditional in the WHERE clause is unavoidable. Besides, the actual SQL being executed in the various cases is a lot more complicated than in this example and having that copied and pasted throughout the stored procedure is nigh unmaintainable.

My solution to this problem was initially to build me a SQL statement in .NET code and execute it. This is usually a pretty reasonable approach. Easy to implement and easy to follow, even if the SQL that you generate isn't. A purist will tell you that it should be in a stored procedure because of the performance and the security concerns and the fact that the DBA just read in a book somewhere that hard-coded SQL was bad.

But in many situations, the performance hit won't be noticeable and depending on your requirements, the security aspect may be moot. The application that spawned this series of articles is an application for my brothers' and dad's company to search for land surveying jobs they've done in the past. Total number of users: six. Security concerns: none. They've been running the current version of the app on hard-coded SQL for over five years now and the only complaints I hear are on lack of features. But what can I say? It's an ASP app and my psychiatrist has forbidden me from looking at it ever again.

But I'm older and wiser now and always on the lookout for ways of making my code not look like it was done by someone just out of high school. So I needed a way of addressing these two issues.

The problem with the delimiited list, it turns out, is pretty easy to solve. I'll describe the thought process I'd like to think I would have gone through had I solved it myself rather than just searching Google Groups.

Like most things in SQL, there are many ways of approaching a problem. Do you use INNER JOIN or a filter in a WHERE clause? Temporary table or table variable? Return a rowset of one column and row or a scalar?

When we examine the problem of filtering on a delimited list of values, we should consider that maybe there's another way of filtering rather than using IN or even WHERE clauses. Namely, using INNER JOINS. What if we had a table of ClientIDs that contained only the ones we wanted to filter on? Then we could do an INNER JOIN on that table, automatically filtering out the ones we don't want.

We know we can declare table variables so our problem reduces to: How can we convert a delimited list of values into a table? Again, judicious use of Google keywords leads us to a SQL function that does just that.

In the database, you'll notice a function called UTILfn_split, which I found here. The function is easy enough to understand from a black box perspective: you pass in a delimited list and a delimiter and you get back a table.

In three places, you'll see code that looks like the following:

      -- Get a list of ClientIDs
      IF @clientIDList IS NOT NULL AND @clientIDList <> ''
      BEGIN
            INSERT INTO @clientIDTable
            SELECT            [Value]
            FROM        dbo.UTILfn_split( @clientIDList, ',' )
      END
      ELSE
      BEGIN
            INSERT INTO @clientIDTable
            SELECT            ClientID
            FROM        Clients
      END

In words: If a list of client IDs was passed in, populate my client ID table with the values in the list. Otherwise, populate it with every client ID in the system.

The reason for the IF statement, of course, is that an @clientIDList indicates that we don't actually want to filter on clientID. But we still need to populate the table with something because otherwise, we'd have some conditional logic to determine if we want to do an INNER JOIN, which as far as I know, isn't possible.

Now that we have a table variable with all the client IDs from our filter, the rest of the SQL is easy:

      SELECT      *
      FROM        MOO m
      INNER JOIN  @clientIDTable ct
      ON          m.ClientID = ct.ClientID

That is: Get me all the values of Moo that have a matching Client ID in our @clientIDTable variable.

The second issue isn't quite as clean but still lends itself to stored procedures. Earlier, I mentioned that we would need some sort of conditional construct in the WHERE clause to determine how to filter on the Moo Name. While this is true, I kind of lied when I said we were limited to IF and CASE.

This is probably easiest to discuss after looking at the WHERE clause:

      WHERE
       (
                 ( @nameFilter = 'startswith' AND m.Name LIKE @name + '%' )
       OR        ( @nameFilter = 'endswith' AND m.Name LIKE '%' + @name )
       OR        ( @nameFilter = 'exactly' AND m.Name = @name )
       OR        ( @nameFilter = 'contains' AND m.Name LIKE '%' + @name + '%' )
       OR        ( @nameFilter NOT IN ( 'startswith', 'endswith', 'exactly', 'contains' ) )
       )

So what kind of magic is this? This is easier to understand if you look at the individual pieces of the clause (i.e. the ones separated by OR). The first segment says:

      ( @nameFilter = 'startswith' AND m.Name LIKE @name + '%' )

This is a little easier to follow. Return all results where Moo.Name starts with the specified value but ONLY if @nameFilter = 'startswith'. If @nameFilter doesn't equal 'startswith' this, of course, will fail and we move on to the next OR to see if that succeeds:

      ( @nameFilter = 'endswith' AND m.Name LIKE '%' + @name )

This is a very similar condition. Return all results where Moo.Name ends with the specified value but ONLY if @nameFilter = 'endswith'.

Looking at the two conditions together, if @nameFilter = 'startswith', the first condition will be met and we'll filter on @name + '%'. If @nameFilter = 'endswith', the first condition will not be met but the second one will and we'll filter on '%' + @name. If neither condition is met, we move on to the rest of the statement.

The trick here is to ensure that all possible cases are covered when you compare against @nameFilter. That's why the last condition is:

      ( @nameFilter NOT IN ( 'startswith', 'endswith', 'exactly', 'contains' ) )

This is a catchall. By including this, it means that if @nameFilter doesn't equal one of the previously handled values, don't filter on Moo.Name at all. Which is why there isn't a filter condition after it as in the other ones.

Using these two techniques, along with the usual SQL suspects, we are able to get a pretty robust search mechanism in our stored procedure. If we wanted to, we could also combine this procedure with Microsoft Index Services. This would allow us to not only search metadata about a group of documents, but also search the contents of the documents themselves. A cost-effective way of doing document searches for cheap-ass family members who don't want to buy Windows 2003 for Sharepoint Services.

I should mention that there is now another way of addressing this problem, thanks to SQL Server 2005. That is, you can use SQL Server's CLR integration to run managed code directly from the database.

I'm making it sound like I know more about this than I do but I haven't actually done this in any way, shape, or form. From what I've heard, though, it is probably a very viable alternative, provided you are targeting SQL Server 2005 in your application. At the very least, you could probably replace the UTILfn_split function with managed code as it probably runs much cleaner and faster in the CLR. And I'm guessing you could make use of an enum for the @nameFilter parameter which would be a little less unstable. I'm sure I'll blather on this when I start experimenting, though.

Finally, credit to http://jargon.watson-net.com/ for the web service I used to generate the data. At present, the database has only fifty entries in the Moo table but if you navigate to SearchPontification/GenerateData.aspx, you can generate more. Note that since this is a web service, it will take a bit to generate each word so be prepared to wait if you put in more than, say, 100.

Tuesday, May 02, 2006

So on the recommendation of alert (and as far as I can tell, only) reader Brian Sherwin, I checked out qliner's HotKeys application, an open source Windows key mapping utility. At first glance, it appeared to do all I wanted and more.

Here's what I liked:

  • Very clean interface. The online keyboard gives a great overview of which keys are mapped to which functions. The developer clearly put a lot of effort into little details like making icons animate to the bottom right corner of the key when they are moved.
  • The volume control is great. It was this feature that *almost* made me dump WinKey.
  • Support for different keyboards (which, I admit, I would never use).
  • Open source and written in .NET. And the developer appears really responsive to feedback and eager to address issues.

But there are two things that keep it from replacing WinKey:

  • The keyboard stays onscreen only as long as you hold the Windows key down. Let go of the Windows key and the keyboard goes away. Not only is this awkward, it's a little confusing if you let go of the key while a dialogue or context menu is open.
  • No support for Shift+WinKey, Ctrl+WinKey, or Alt+WinKey. In WinKey, I have Win+G mapped to Google and Shift+Win+G mapped to Google Groups. I'm just getting into Windows key mapping and will probably use other similar combinations.

Both issues have been brought up in the forum and I have no doubt they will be addressed shortly, at which time, I'll promptly switch from the all-but-defunct WinKey. There is also talk of being able to override the default Windows key combinations which will be sweet. And if the developer is smart, he'll open it up for others to add their own controls similar to the volume control. Like Media Player controls (i.e. Play, Pause, Next, etc.).

Friday, April 28, 2006

There are two phrases that I simply don't allow people to say to me. They are: “quick question” and “simply”. Depending on its usage, “just” is just as questionable. (Yes, I know I've used two of the forbidden phrases in the last three sentences. The Coding Hillbilly is nothing if not a grammatical and hypocritical enigma.)

Nothing good ever follows these words so I have some canned responses when I hear them:

  • You ask the question and I'll tell you if it's quick
  • And why don't you “simply“ fix that ticking sound in your car engine?
  • I'll get right on that. I “just“ have to rebuild this server first.
  • The question may be quick. The answer won't. (Memory's fuzzy but I believe credit goes to Rajeev for that one.)

Any other verboten words and phrases I should add? I'm always up for a little personal censorship.

Monday, April 24, 2006

I read an interesting discussion somewhere a couple of weeks ago on comments. Pretty much everyone in the discussion was unanimous in their stance: if you write your code well enough, comments are a waste of time and may even be dangerous.

I shall rebut from afar because I don't remember where I read this and even if I did, I don't feel strongly enough about the topic to start a flame war. Because I just know I'm going to end up calling these guys idio--oh bother...

Some interesting points were brought up, two of which I remember. Firstly that if code is written well, it should be clear what it is doing and comments are moot. Secondly, since developers are generally a lazy species of human, we don't generally update them as often as we should and over time, they can end up being flat out wrong.

Seems to me that these are contradictory. I.E. If a developer is too lazy to update comments, do we trust him or her to write code that is easy enough to read without accompanying documentation? But I'll forego my analysis into the mind of a programmer and argue why I write comments religiously.

For the most part, I'm a .NET developer and mostly in C#. Visual Studio has colour coding for a reason. Comments are in green, keywords blue, code black (barring customisation). Which makes it much easier to tell where one function ends and another begins, provided you preface every method with a comment. And even if you're too lazy to type “this method does blah”, how hard is it to type /// at the beginning of each method to at least put in the

stub? Even when you look at code outside Visual Studio, it's easier to pick out the methods when there are three lines of /// before each one.

My second point addresses the misguided and delusional idea that code can always be clear. It can't. Plain and simple. I write business apps in which the problems are pretty easy to decipher and there are still algorithms that can get pretty complicated. In many cases, there are half a dozen ways of doing something. Maybe you've tried two or three and run into problems. Throw some comments in to the effect of “I tried this with a serializer and it threw this error.“ That way, when the serialization expert sweeps through, he'll have the benefit of your hard work before he runs into the same error during a refactor.

But let's assume you are able to create this universally comprehensible code that describes exactly what your function is doing. What about a piece of complicated business logic that spans several functions, and possibly several classes? Sure you can glean what you're doing from the individual function names and their internals but what would you rather read: well-written code in several places or even rudimentary comments in one place?

I'll grant that there is a danger that comments can become outdated over time. That's to be expected (but not necessarily accepted, which it generally is). I would counter that the same argument can be made about well-written code. On the first pass, you create magically-named functions and variables which have no double meanings (which means they clearly don't contain any English words). Then during your QA, a tester says: “Wait a minute. You're supposed to discount the interest here, not compound it.”

So you fix the code, then update all your function names that say “compoundMyValue” so that they now say, “discountMyValue”, right? Of course you do. No matter how close you are to deadline, you always have time to rename the functions in your entire project so that they are abundantly clear for the support person that's coming in tomorrow. The unit tests will catch any you've forgotten because, naturally, you've been keeping all those up to date, too.

Ignore the naysayers and for Jayzus' sake, comment your code. How hard is it really? It can be fun. It's one of the few places we can be creative. You don't need to go overboard and comment every line and every variable. But putting in something that says “Create another hashtable to cache our assemblies as we load them“ can be pretty useful for the next person that has to read your tripe.

And if you really want to stand out, make it sound like the Swedish Chef wrote the code.

Monday, April 24, 2006

I think I'm finally getting used to user instances in SQL Server Express to the point that I now know that they're called “user instances”. The annoyance I mentioned in a previous post is explained here. Specifically:

The other main issue with user instances occurs because SQL Server opens database files with exclusive access. This is necessary because SQL Server manages the locking of the database data in its memory. Thus, if more than one SQL Server instance has the same file open, there is the potential for data corruption. If two different user instances use the same database file, one instance must close the file before the other instance can open it.

Who knew reading documentation could be so helpful? We've come a long way in such a short time.

The net effect of this is that it'll be a while before I change my habits enough to use SQL Server Express effectively. And frankly, there are only two cases I can think of for using it at all:

  • Windows Forms applications that use a local database (i.e. the database is for that instance of the application and nothing else)
  • Web applications built specifically for people to download as test code

The second one is where I first encountered SQL Server Express which is why I had all my problems. I saw this database in some sample code and said, “Cool, I can work with the database directly in Visual Studio” not knowing the repercussions of my funky way of debugging. In the meantime, I'll stick with SQL Server Developer Edition and export to an Express database should the need arise. (*UPDATE*: Easier said than done)

Also, it looks like there are a bunch of SQL Server downloads this week, including SP1 for all versions of SQL Server (NOTE: SP1 for Express is a separate download than other versions). Includes a full-fledged, non-CTP version of Management Studio for SQL Server Express so if you're using that version, have at it. Some other related downloads with Advanced Somethings and Toolkit Thingies but none of them looked interesting enough just yet.

PART 2
Was going to post this separately but I don't want to look like I'm padding. Plus it's related to Part 1

I've discovered another reason I don't like SQL Server Express. In another post, I mentioned that I love me some SQL Profiler. This is even more important in the Visual Studio 2005 world because of how easy it is not to write code. I've been playing with binding GridViews to ObjectDataSources and it's pretty cool when everything works. Last night, I went through this long exercise of building up the database for the second part of my search article and building a quick search interface that uses a GridView bound to an ObjectDataSource.

So I configured my table adapter, configured my GridView, configured my data source, and clicked GO. Net effect: a blank page. No errors, no warnings, just a blank page.

So what went wrong? I can't tell because: a) there's no code to step through, and b) even if there was, it's not going to tell me exactly what SQL was executed. SQL Profiler, on the other hand, can. I started up a profiling session, refreshed the page, and there it was: the exact stored procedure call complete with parameter values.

By the way, I've found that you can get more use out of Profiler if you set up your own template with a filter of: Application Name LIKE .Net SqlClient Data Provider. This ensures only activity performed by your application is recorded in the trace. I imagine you can probably tweak the included TSQL template to do the same thing but I'm not much of a DBA. Once I get something working in that regard, I just want to get back to my code.

Last little whing against Express, I promise. I use a subst'd drive for my projects, in this case P:. All versions of SQL Server work less than well when you try to connect to them from a subst'd drive. So when I throw a database into my app that is resting in P:\RumRunner, I get errors from the git go. I essentially have to toss out the solution and reconnect to the app from the absolute path.

This problem might go away because I've since learned about junction over at www.sysinternals.com. I'm giving some consideration to this approach rather than subst'd drives after listening to a podcast on the tool. (OK, it was Hanselman's podcast again but I'm not linking to him because he's gotten enough press from me. Oh, all right.)

But now that I think about it, I like having a separate drive for my projects. More than I like having to navigate through the tree view in Management Studio to get to database files the long way. And the obsessive compulsive in me is not going to take lightly to a bunch of junction'd drives cluttering my C: drive. Then again, the ADD in me might win out long enough to try it...

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

Copyright © 2010 Kyle Baley. All rights reserved.
 
CATEGORIES
.NET General (18) alt.net (4) altnetconf (9) ASP.NET AJAX (40) ASP.NET MVC (29) Bahamas (1) Bahanet (9) BDD (1) Brownfield (18) Career (9) Castle (1) Code coverage (1) Coding Style (6) Communication (1) Community (18) Conscientious Coding (34) Continuous Integration (11) dasBlog (12) Development (16) DevTeach (4) Domain (2) Environment (4) Estimating (1) Featured (14) Flamingo (10) Games (1) Google App Engine (2) GWT (5) Hardware (6) Java (1) Javascript (7) Linq (2) Livelink (6) Lucene.NET (2) MbUnit (1) Metrics (1) Miscellaneous (24) Mocking (4) NAnt (4) NHibernate (12) NInject (1) Office (3) Office Development (6) Open Rasta (1) Patterns (5) Presenting (13) Professional Development (15) Refactoring (10) ReSharper (11) REST (2) S#arp Architecture (5) Security (3) Software (11) Sundry (18) TDD (19) Tools (21) User Interface (5) Utilities (8) Visual Studio (8) VSTO (1) Web development (12) Windows (3) Working Remotely (16) Workplace (3) Writing (4)
 
LATEST POSTS
 
POPULAR POSTS
 
 
ARCHIVE