Extending DbSet for easy filter expressions

Databases often have entities which are often by a repeated expression. A common one is filtering something by a UserId. In SQL, this looks like:

select * 
from orders
where userid = @userid;

Using Entity Framework, we may write something like this:

dataContext.Orders.Where(x => x.UserId == userId);

But I’d really like to make it more expressive and consistent, like this:

dataContext.Orders.ForUser(userId);

Fortunately, it is possible, with an interface and an extension method.

The interface, which I will call IUserEntity, will expose the common filtered expressions.

public interface IUserEntity
{
	int UserId { get; set; }
	User User { get; set; }
}

Any class that can be filtered by users should inherit this class.

public class Order : IUserEntity
{
	public int Id { get; set; }
	public int UserId { get; set; }
	public User User { get; set; } = null!;
}

Then our expression method will extend any DbSet with a type of IUserEntity to include our extension method, which simply returns a filtered DbSet.

public static class DbSetExtensions
{
	public static IQueryable<T> ForUser<T>(this DbSet<T> userEntities, int? userId) where T : class, IUserEntity
	{
		if (userId.HasValue)
		{
			return userEntities.Where(x => x.UserId == userId.Value);
		}
		return userEntities;
	}
}

Note how in the above I made the userId nullable — this is not required, but it does give you a bit more flexibility.

This can be replicated for any other common filter, which will make your code more expressive and easy to read. If you wanted similar extensions on other elements, such as Lists, you could just make a copy of the extension method for that object type, and the appropriate return types.

Is Verizon FiOS TV in your area? Don’t try checking online.

It seems I always have usability issues with Verizon‘s web sites. After checking to see if, after two weeks, they figured out why an old cell phone number of mine was still showing up on my online profile (they didn’t, it’s still there), I decided to see if FiOS TV was in my area.

They have a nifty Check Availability page where you enter your phone number (if an existing Verizon customer) or address to find out if you can get this service. Being a Verizon customer, I enter my phone number, click the “Can I get it” button, and wait…

While you wait, you do get a little graphic that is somewhat more useful than a spinning Ajax cursor.

image 

So, is FiOS TV available to me? Well, I don’t know. The response you get says nothing about FiOS TV — instead, it tells you about your FiOS internet service.

image

But wait, that isn’t what I asked! I wanted to know about FiOS TV! I am well aware that I already have FiOS Internet Service.

Alas, there’s apparently no easy way to find out online. Sometimes, you just can’t find what you’re looking for.

Unrelated but related — why did they spell it FiOS? Why the lower case “i”? Was FIOS ruled out for some reason? Or is it an acronym where only the F, O, and S dictate new words (perhaps Fi is for “Fiber”)?

According to Wikipedia’s FiOS article, “Verizon has cited the fact that “fios” is an Irish word for “knowledge.” If that’s the case, couldn’t they just make it FIOS? After all, it’s so hard to type FiOS… Maybe a marketing guru told them that the lower case “i” makes it “cool, hip, and Web 2.0.”

In any case, look elsewhere for your FiOS TV availability.

Free file archiving and (de)compression with 7-Zip [with expensive minimum donations]

In thinking about all the free and open source tools I use, one seems to run underneath the radar: 7-Zip.

7-Zip will compress, expand, encode, and decode more formats than you can shake a stick at. It integrates seamlessly with Windows Explorer, so you just right-click and choose the option you want, as shown below.

image

[That little fuzzy thing in the background is my dog, Thea. How I miss her!]

The fact that 7-Zip does so much and is free makes me wonder why anyone would pay $30 for a copy of WinZip. Instead, donate that money to Igor Pavlov, author of 7-Zip.

I decided to do just that. Heading over to the donate page for 7-Zip tells you that the “base donation amount is $50 or €40, but if you would like to donate more, just change the Quantity field”. Apparently, you can donate more than $50, but you can not donate less than $50 — donations must be whole-number multiples of $50.

This is a bit odd. I would think a minimum donation for a free product would be less than the retail price of a commercial product. I wonder how many people don’t donate due to this high number?

Considering that 99% of the archive files I receive are ZIP files, that Windows can compress and expand ZIP files (albeit slowly), and that minimum $50 price tag, I’m going to pass. If Mr. Pavlov would let me set a lower donation level, I’d be happy to oblige; until then, I have that weird feeling I get when there’s a minimum tip amount added to a restaurant bill.

I guess I’ll look for another free/open-source product to send my money to.

ATI video drivers may be more stable than nVidia drivers (but does it matter?)

A friend of mine (who is a reseller for Diamond Multimedia) forwarded me an email last night which shed some interesting insight into video card driver stability with Windows Vista:

ATI Provides Proven Driver Stability

Microsoft is currently involved in a class action lawsuit regarding problems with its “Vista Capable” marketing. As part of this trial, hundreds of pages of internal Microsoft emails were unsealed. If you want to take a look at them, here they are (pdf). Aside from providing some interesting insight into what goes on internally at Microsoft leading up to the release of a new OS, there is also a ranking of the cause of crashes logged with Microsoft.

The rankings, based on crashes logged with Microsoft in 2007, paint a very positive picture of ATI’s graphics drivers. For instance, 28.8% of all Vista crashes were caused by nVidia drivers, compared with 9.3% caused by ATI. When you adjust for market share, we still see that Vista systems are almost half as likely to crash when using an ATI graphics solution…

Author: Blake Eggleston

Now that may be marketing gumbo, but if not, it’s very intriguing.

Of course, the one critical fact missing is how often crashes are caused by video drivers. Do video drivers cause crashes once every 50 hours? 100 hours? 1,000 hours? More than that?

If I use a computer 80 hours a week (rough estimate), a crash every 80 hours is a crash once a week. To me, that’s too much. However, if a crash occurs every 800 hours, that’s one crash every 10 weeks, something which I can tolerate.

As the saying goes, “Better is the enemy of good enough.” nVidia drivers are likely “good enough” — so the “better” ATI drivers (if the claims are true) don’t really matter much, at least not to me.

Connecting to MSSQL with Apache and PHP on Windows

I set up a Windows server as a WAMP server (Windows, Apache, MySQL, and PHP) to run vBulletin. Everything worked fine, and the learning curve was pretty short.

Then I tried getting PHP to connect to a remote Microsoft SQL server. Sorry, no luck!

The apparent fix required an updated ntwdblib.dll. The one that came with the latest PHP5 bits (5.2.6) was apparently out of date (version 2000.2.8.0). A newer one, which I founded linked to from a UserScape support page, is version 2000.80.194.0. Shut down Apache, download the newer DLL (replacing the old DLL), and restart Apache. Viola! Hello, MSSQL server.

Eight cores, four gigs, ten raids, oh my!

Last week, I dealt with an outage of my “business-grade” Internet connection for the last time. The solution? A managed server, courtesy of SoftLayer.

For a pretty darn good price, I get full access to a dual quad-core server with 4 gigs of RAM and 500GB of usable disk space in a RAID10 array. Add in an awesome web-based control panel, an excellent sales staff (thanks, Michael!), and provisioning in less than two hours, it seems like the right decision so far.

It’ll take some time before I migrate completely to this new rig, but until then, I can enjoy the following scenery.

image

Automatic downloads and usability

I just went to download the latest release of GraffitiCMS (which is rather impressive), when I noticed this on their download page.

Thanks for downloading Graffiti!

We know you’re excited about building your new Graffiti site, but please be patient as your download is being prepared. If you click the link below, you will experience a delay in processing.

If your download doesn’t start after you count to 10 backwards in Roman numerals, please click here.

First, I thought it was interesting that they said "If your download doesn’t start after you count to 10 backwards in Roman numerals, please click here." Then, I started wondering… is this the best way to deliver a download to users?

The "automatic download" is rather ubiquitous — nearly all web sites use it. Some questions I wonder about…

  • What percentage of users get the automatic download? How close to 100% is this number? If it’s far from 100%, should we rethink the approach?
  • For those who do get the automatic download, is it something they are comfortable with? Do they typically respond correctly to the browser’s response ("open/save" prompts, or those silly IE slide-in alert bars that people tend not to see)?
  • For those who don’t get the automatic download, how long does it take them to figure out how to initiate the download manually? What’s the abandon rate?

I don’t know the answer to any of those questions, but on the surface, I’d think a better approach (using the GraffitiCMS example above) would be to not have an automatic download. Instead, change the text of the page to the below, and have a big [START DOWNLOAD] button.

Your Graffiti download is ready!

We know you’re excited about building your new Graffiti site. Please click the Start Download link below to get your copy of Graffiti.

[START DOWNLOAD]

I wonder if an approach like that is more useful to users, and has a lower abandon rate than the automatic download approach…

Castle now accepting donations (and getting one from me)

Castle Project is a wonderful thing. I still don’t understand a lot of it, but it’s darn impressive, and has become my library of choice. It’s also no coincidence that my long-sought departure from ASP.Net WebForms was timed with my discovery of Castle MonoRail.

Hammett (the man behind Castle) has finally started accepting donations for his work. I have one thing to say to him:

"It’s about time!"

I know first-hand what it’s like to spend a lot of time on something that:

  1. a lot of people use, and
  2. does not bring in any money (at least, not directly)

My pain has been CSFBL, which today does accept donations (and I truly appreciate every one of them!).

Thinking about this more, it’s been six months since I’ve donated to an open source/free project (I promised last year to donate $5 per month to one), so in order to catch up, I’m sending Hammett $30 ($5 per month). Let’s hope the exchange rate is favorable to him!

My open source donation history to date far is as follows.

Thanks for all your hard work, Hammett, and I hope you can afford yourself a nice vacation for the donations you receive!

Bad programming examples (part 1 of x)

There’s no end to the number of bad programming examples we’ve seen in the past or will see in the future. Recently, I saw this one. (This was actual code seen in an actual project.)

try { createDate = Request.Params["createDate"]; }
catch (Exception) { createDate = "-1"; }

Nice and ugly. Aside from a horrible way to implement a try/catch block, it screams of performance issues and unreadable code.

A more proper alternative follows.

createDate = Request.Params["createDate"] ?? "-1";

The same project also had this use of integer parsing.

try { myInt = Int32.Parse(textBox.Text); }
catch (Exception) { myInt = -1; }

In this case, you would use the TryParse method instead:

if (Int32.TryParse(textBox.Text, out myInt))
    myInt = -1;

Exception handling is for exceptions, not for null checking or validations.

Cancel (and renew) WebEx MeetMeNow to save $10 per month

I recently tried WebEx‘s MeetMeNow service (14-day trial). When the trial expired, I figured I’d cancel it — not because it wasn’t good (it was) or because it was too expensive (only $49/mo), but because I wasn’t sure if I’d need it in the next 30 days, and figured I could just renew the subscription right before the next time I’d need it.

I clicked the Cancel link, and was given a special 20% offer to change my mind. OK, I changed my mind again — deciding to keep the service at the $39/mo price.

The tip here? If you want to save $10/mo using MeetMeNow, sign up for the free trial, then cancel, then accept the service at $39/mo. Can’t argue with the marketing — it snookered me in. 🙂