July 21, 2010
@ 05:15 PM

A common pattern you tend to find in maintenance forms is the ability to open another form so you can add/edit/maintain some list of items. When you return back to the calling form you want to refresh a combo or grid to reflect the changes. The way most of us do this is to make the maintenance form modal. When you call it, code execution stops until the form is released. That works but it can break down if you find yourself more than 1 level deep in maintenance forms – the user can’t easily move windows out of the way to see information and you’ll occasionally find that the wrong form has somehow gotten focus leaving you stuck (unable to get focus back to the correct form).

Here’s an example. The user starts off on the Client Maintenance form, then clicks on the Commissary button (military grocery store) to select which stores are associated with this client. Then they click on the Commissary button again if they want to add/edit a new store. When they close this form we want to refresh the second form.

 

image

Again, the normal way you might do this is to make the third form modal.

DO FORM CommissaryMaintenance
* When the form is closed the code below is run which saves and refreshes
* the options shown.
ThisForm.SaveAndRefresh()

An alternative to this code (and making the form modal) is to do something like this instead:

DO FORM CommissaryMaintenance NAME loForm
BINDEVENT(loForm, “Destroy”, ThisForm, “SaveAndRefresh”)

Now the form can stay modeless. We’re taking advantage of VFP’s BINDEVENT command. When the form is closed and the Destroy() event fired we’ll fire the SaveAndRefresh() method which refreshes the form. It’s simple and avoids the problems mentioned above.

One suggestion is to add code in the calling form to set focus back to itself (in case you are mixing and matching modal and non-modal forms). Ex. in the SaveAndRefresh() method you might want to do something like this:

ThisForm.grdList.SetFocus()

That will ensure that your form actually gets focus and back where the user is expecting to be.

This all works great, but what if you want to update the form as new items are add, not just when the form closes? If you modify the maintenance form to call an empty method after a successful save, ex. create a method named SaveSuccessful() you can now bind to this method instead of Destroy().

BINDEVENT(loForm, “SaveSuccessful”, ThisForm, “SaveAndRefresh”)

With only an extra line or two of code you can get rid of the modal form and still have your calling for get easily updated/refreshed when things are changed.


 
Categories: VFP

Interfaces are an integral part of .NET, yet a lot of new .NET developers (especially those coming from weakly-typed languages, or languages where interfaces aren't supported) have difficulty in understanding why they're needed and how (and when) they're used. If you find yourself in that group you're in good company. It's not a difficult concept but it can be a bit foreign to developers new to them.

Let's get the textbook definition out of the way, then take a look at what it really means (and why you should even care). From Wikipedia:

"Interface generally refers to an abstraction that an entity provides of itself to the outside. This separates the methods of external communication from internal operation, and allows it to be internally modified without affecting the way outside entities interact with it, as well as provide multiple abstractions of itself. It may also provide a means of translation between entities which do not speak the same language, such as between a human and a computer."

Hmm - OK. While technically correct that doesn't really help, does it? Did your eyes glaze over like mine did while reading that? Maybe if we back up a bit and look at what a class is we might be able to make some sense of this.

The Basics

A class is a collection of methods, properties, and events. It is assumed that each of these methods, properties, and events "do something". At least in most cases (we're going to ignore the idea of an abstract class for right now). So far, so good. You can create a new instance of this class and do things with it, pass it around to other classes as a parameter, etc. In a weakly typed language (also known as a "dynamic language") you can pretty much pass any type of class around without having to worry about the type - as long as your code doesn't try to access a property or method that object doesn't have, you're good to go. The upside to this is that it's pretty flexible. The downside to this is that mistakes aren't caught at compile time - your app. just blows up at runtime (so you'd better test!). Strongly-typed languages take a different approach: you must define the types that can be passed as parameters to methods. That's OK as long as there is only one specific type your method acts on, or the type you're passing in inherits from the base type of the parameter - it's pretty straightforward. The upside is that mistakes (like trying to access a property or method that doesn't exist) is caught at compile time. The downside is that it's not as flexible as a dynamic language.

So what do I mean by "not as flexible"? On the surface it seems pretty reasonable that a strongly-typed method only accepts specific types - how else would the compiler (and you) know that it's safe to access a specific method or property? It doesn't. It only can accept that specific type of class, or any subclass of that same type.

Why is it OK to accept a subclass of the type? Well, the compiler can be sure that the subclass has the same exact properties & methods as its parent (it doesn't care if you add more of them or override the behavior).

But what if it doesn't? What if you had a class that wasn't of the correct type necssary to pass into a method and it didn't inherit from that type either? Let's take a look at an example of this. I wanted to keep it simple enough to understand, but have it be a REAL scenario (not some contrived example). Those goals are a bit difficult to balance so I error'd on the real scenario side of things. Hopefully it'll help you understand WHY some things are the way they are in the framework in addition to understanding interfaces.

A Real Example

For example, let's suppose we create a collection class that can have a collection of objects (that are all of the same type) and we want to have a method which can sort them. You want to write a generic Sort routine on your collection class that can sort any kind of collection of objects, as long as they're the same type. The first issue you'd run into is, "How do I generically create some code which can compare ANY type?" Remember - you have to be able to compare strings, numbers, date/times, maybe custom types someone may have created, etc. So it's not really possible to be able to compare ANY type. You could cover the basic types and then require the user to subclass your collection for any other custom types. It's a bit clunky, but it would work.

What if, instead, we decided that we'd have another class responsible for doing the sorting. We'd provide a default implementation and if you had your own custom types that needed to be sorted you could pass in your own implementation. That's a bit better. The developer would still need to subclass from our default implementation (since we've still got the strongly-typed issues here - again, dynamic languages don't have this "issue"). We could have the developer pass in their version of the class which does the comparison into the Sort() method. The passed in class would have a Compare() method and let's say it takes two parameters of the types of the same type of object and returns an integer value indicating whether one of the objects is less than, greater than, or equal to the other.

Let's take a look at what the code might look like for all of this:

public class Comparer
{
    public int Compare(object x, object y)
    {
        // Code to do comparisons here
    }
}

public class SampleArrayList
{
    public virtual void Sort()
    {
        this.Sort(new Comparer());
    }

    public virtual void Sort(Comparer comparer)
    {
        // Do sorting here. Call out to comparer object to do the actual comparison
    }
}

 

SampleArrayList list = new SampleArrayList();
// Add items to the list
list.Sort(); // default implementation
list.Sort(new SomeComparerSubclass()); // A custom sort


That looks OK. If I wanted to create my own comparison class all I'd do is subclass from Comparer and override Compare() with my own implementation. But let's take a step back and think about this for a bit. If you create a new class and want a method that can compare one instance of that class to another instance of it, where's the best place for the code? Doing comparison's is a pretty fundamental capability of a class - we do it all the time with string's, numbers, datetimes, etc. so clearly it belongs with the class, right? Your only other alternative would be to put it into another class that acts as a kind of "helper". That's effectively what we've forced on any developers that want to use the sorting capability of our collection for their own custom classes. They MUST create a helper class to do a comparison or they'd all have to inherit from our Comparer class (and use it as their base object). That might not be the end of the world but we're only talking about a single example - there are a lot of other places where this scenario comes up.

OK, having to create another class which only does a comparison for a specific type isn't all that great. Since it makes more sense to have a comparison handled by the object being compared, let's say we add a method called CompareTo() to any class when we want to be able to compare it against another instance. In our Comparer class we'll call that method and, hey, our comparer class is now a bit more generic right? We know that in .NET all objects inherit from "System.Object" so having our Comparer class's Compare() method accept "objects" means we can use it with ANY type. I don't actually have to create a new class for each and every item I'm going to compare! But wait - we're STILL going to have the problem with calling the CompareTo() method on our class in the collection; we're back to having to inherit from a common base class.

 

public class Comparer
{
    public int Compare(object x, object y)
    {
        // Code to do comparisons here
        return x.CompareTo(y.CompareTo());
    }
}

But now how can we call the CompareTo() method on those objects? How do we even know if those objects have a CompareTo() method? Since .NET is strongly typed you can't do this - it won't even compile. The class type "object" doesn't have a "CompareTo" method. The .NET compiler knows that and it won't let you do that.

This is begining to feel like a circular issue, isn't it?

Breaking the Cycle

OK, now what? Well, you could jump through a lot of hoops and use reflection to make the method call for you. But it's a lot of work. In a dynamic language (such as Visual FoxPro) code like that is perfectly valid - I can pass any object type into a method like that and access any properties or methods and VFP doesn't care. If the object doesn't have those properties or methods it will just blow up at runtime. I'm a good developer so I won't pass in something that would blow up. .NET sucks - it makes things so difficult.

You're basically stuck at this point - you can't do what you'd like to do in .NET. If .NET supported the idea of multiple inheritance (where class C could inherit from Class A and from Class B at the same time), we'd be able to still make this work. But it doesn't.

Interfaces to the Rescue

That's where interfaces come in (finally!). Let's take another stab at a more concrete definition of an interface: An Interface is a definition of the types of properties, events, and methods a class needs to implement. It's nothing more than a list of properties, events, and methods (and the various types associated with them) that a class has to have. While we can't inherit from multiple classes in .NET, we can inherit from multiple interfaces.

Getting back to our example, we could define an interface that consists of a public method called CompareTo that accepts one parameter of the "System.Object" type ("object" for short). This method needs to return an integer: Less than zero means this instance is less than the object passed in, zero means it's equal, and greater than one means it's greater than the passed in object.

Here's what it might look like:

public interface IComparable
{
    int CompareTo(object obj);
}

While we're at it, it seems like we might want to do something similar to our Comparer class:

public interface IComparer
{
   int Compare(object x, object y);
}


Now all we'd need to do is make sure that any class that we want to compare inherits from the IComparer interface and then "implements" the specified properties, methods, and events (PEM). That is, you need to make sure your class has all of the same PEM's as the interface. Then you use the interface as the parameter type instead. Since we can inherit multiple interfaces on a given type we have a way of giving our classes the cameleon-like ability of appearing as exactly the right type to methods, regardless of what class it really inherits from. We'd do the same thing for any class which can compare two different classes.

So we can rewrite the above code:

public class Comparer : IComparer
{
   public int Compare(object x, object y)
   {
       // Code here which compares x to y and returns integer
   }
}

public class MyCustomClass : IComparable
{
   public int CompareTo(object obj)
   {
   }
   public int CompareTo(MyCustomClass obj)
   {
   }
}


And we rewrite the Sort() method on our collection class SampleArrayList to accept objects of type "IComparer" instead of "Comparer": 

public void Sort(IComparer comparer)
{
   // Code here that iterates over the collection and class Compare()
   // with two of the items in our internal list.
}


Suddenly all of this starts working again - you get compiler-time checking to make sure things don't blow up, Intellisense works, etc. In fact the compiler verifies that you have, in fact, done all of this correctly - if your classes don't implement IComparer or IComparable it will let you know. You have the ability to create a custom class that compares objects in different ways (which makes it easy to come up with different ways of sorting, ex. ascending, descending) and have generic code which will work in most cases.

Conclusion

The scenario I described above plays out throughout the .NET framework. Fundamental things like garbage collection are handled via the IDisposable interface, iterating over a collection (think foreach) is handled by IEnumerable, comparing objects (like we described above) is handled by IComparer and IComparable. Interfaces are used extensively. Hopefully you've gotten a feel for why they're needed and how they're used inside of .NET.

Originally published in Universal Thread Magazine, April 2009


 
Categories: .NET | C#

July 15, 2010
@ 05:55 PM

(This is here just as a reminder to myself)

To forward calls on Sprint:

  • Dial *72 plus the area code and phone # you want to forward calls to
  • Hit the Talk/Call button.
  • When you hear the tone, hang up.

 To cancel call forwarding:

  • Dial *720
  • Hit Talk/Call.
  • When you hear the tone, hang up.

 
Categories: Cellphones

I've been working on a server monitoring Windows service recently - it's meant to keep an eye on our servers for various types of failures and, if possible, automatically recover from them. One of the failures our website experiences once in a while has to do with our forums. I integrated a third party forum package into our site so our stores have a place to post messages and talk with one another. Occasionally (and I have yet to reproduce the failure steps) it will fail, complaining that it can't find some configuration file. The quick fix is to reset IIS; usually I'll just remote into the server and do an IISRESET from the command prompt. I wanted my service to keep an eye out for this type of failure and automatically recycle IIS. Long term I'd love to track down this failure and fix it the proper way but in the meantime I just want to be able to recover gracefully.

I found the ServiceController class after a bit of digging and wrapped it up into two static methods I could call to reset IIS. I just had to figure out the name of the service I needed to refer to. The easiest way I found of finding this was to just cycle through the services and display their names. You could write a quick console app. to do this, but I just used LINQPad, switched it to C# Statements, added a reference to the System.ServiceProcess.dll (hit F4), then added the namespace System.ServiceProcess and ran the code.

As an aside: I can't say enough nice things about LINQPad - it makes it so nice to be able to test out new classes and ideas. Its name would lead you to believe it's only good for testing LINQ queries, but you can test out almost any .NET code you want. I spent the whopping $19 to upgrade to the full version, which adds Intellisense (the free version doesn't include that). I've added LINQPad to my "must have" .NET toolkit.

image

You might be wondering what the Dump() method does, since it's not part of the ServiceController class. LINQPad has a nice extension method named Dump() that makes it trivial to dump out the response from almost anything. My sample doesn't show it, but it even handles nested classes nicely. OK, enough fawning...

I ran this code which made it really easy to find the service names I was interested in. Once I had them I wrapped up a few of the services I wanted to be able to cycle in their own methods. I ended up wrapping the Start/Stop calls in a try/catch; it would throw an exception if I tried starting a service which was already running or stopping a service which had already stopped.

private void ResetIIS()

{

    StopService("W3SVC", 10);

    StartService("W3SVC", 15);

}

 

private void ResetStateServer()

{

    StopService("aspnet_state", 15);

    StartService("aspnet_state", 15);

}

 

public static void StopService(string serviceName, int timeoutSeconds)

{

    using (ServiceController controller = new ServiceController(serviceName))

    {

        try

        {

            controller.Stop();

            controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(timeoutSeconds));

        }

        catch (InvalidOperationException ex)

        {

            // Service may already be stopped

        }

    }           

}

 

public static void StartService(string serviceName, int timeoutSeconds)

{

    using (ServiceController controller = new ServiceController(serviceName))

    {

        try

        {

            controller.Start();

            controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(timeoutSeconds));

        }

        catch (InvalidOperationException ex)

        {

            // Service may already be running

        }   

    }           

}

 

private void ListServices()

{

    ServiceController[] services = ServiceController.GetServices();

    foreach (ServiceController service in services)

    {

        string name = service.DisplayName + " : " + service.ServiceName;

        Console.WriteLine(name);

        //name.Dump();

    }

}


Links:

http://www.linqpad.net


 
Categories: .NET | C#

July 25, 2009
@ 09:00 PM

Last year (two years maybe? Time flies...) I built a web-based "e-mail" system that provided internal-only e-mail on our web portal. That might seem a bit weird, but we needed a system where we could be sure when an e-mail was sent, to who, when it was read, ability to recall a message, control who can send messages to who, etc. Basically we needed to control the content end-to-end. Unfortunately standard e-mail doesn't give you that level of control, so hence the need for building it.

I wanted the e-mail to function very similar to Outlook to minimize the learning curve and help adoption (the old system another provider was hosting was really clunky). It uses a lot of AJAX technology and had what I thought was a fair amount of the standard e-mail features: You can create custom folders, move messages, forward messages, reply to messages, add attachments, it automatically refreshes the e-mail list periodically, you can view who has read your e-mail (and when), group messages by date or sender, sort messages, resize the windows, double-click on a message to view it in a larger window, plus a lot of other smaller features.

 WebEmail

Web Email Move Folder

Web Email New Message

I thought it turned out nicely but an interesting thing happened; Some users were unhappy with the level of functionality provided: you couldn't flag messages, drag and drop a message from the inbox into a folder, the e-mail list didn't have intellisense, etc.

Wow - I totally wasn't expecting that reaction (mind you, it was from a fairly small minority, but it was interesting getting that feedback).

Of course it doesn't compare to the functionality of Outlook, I thought! They had 100+ developers and a few years of development time. I had, well, me and a few months (and not just on this particular module)!

I didn't know what to make of it. I had spent a lot of time adding features, polishing the UI so it wasn't clunky looking, etc. and they weren't happy with the functionality? Where did I go wrong? It didn't occur to me until later that, by mirroring the look and feel of Outlook that I was setting my web-based e-mail client to be compared directly against Outlook. They weren't comparing it to the clunky old system at all. I had inadvertently set their expectations much higher than I could deliver because of this. Ouch.

In retrospect, I might have been better off delivering a system which functioned and looked better than the existing system but didn't attempt to look and/or operate like Outlook at all. For example, if I was able to do this over I'd probably drop the folders option and simplify the e-mail list to just a nice looking grid list w/sorting (removing the grouping altogether) and reduced some of the AJAX functionality (ex. when you click on a message the e-mail icon "opens" and changes from bold text to normal text), among other things. I would have spent less time on it and had less chance for bugs to boot.

I know all about setting a customer's expectations so that there aren't any surprises, but I completely forgot about some of the implicit expectations that can arise in a project (and managing those as well).


 
Categories: Software Development

May 3, 2009
@ 06:36 PM

It looks like I'll be speaking at this year's Southwest Fox 2009. I'll be presenting two different topics:

Full Text Search using Lucene.NET and
Refactoring Legacy Code.

I'm looking forward to catching Craig Boyd's FLLs and the Visual FoxPro API session (assuming the schedule allows it). I had debated whether to interface to Lucene.NET from an FLL, but ultimately decided that it didn't quite fit with the way I imagined it being used. Craig has a number of different FLL's over on his site, so if you've ever wondered how to put together an FLL this should be good.

Christof Wollenhaupt's session, Using .NET in FoxPro Applications should also be a nice companion to my Lucene session. I hadn't planned on covering too much of the interop story in my session, I'll be focusing more on actual use. This should give you a bit more background if you're interested.

Refactoring is a big topic, so you might want to check out Alan Stevens's Break It Down: Dealing With Legacy Code pre-con session. Then check out my session as a refresher and (hopefully) come away with some other ideas on how to manage legacy code. If you can't make the pre-con, hopefully you'll still find my session valuable. I plan on showing real code and some of the ways I have handled refactoring, things to look out for, and various refactoring techniques.

I look forward to seeing you at Southwest Fox.

 

Links

http://www.swfox.net/sessions.aspx#Full_Text_Search_using_Lucene.NET
http://www.swfox.net/sessions.aspx#Refactoring_Legacy_Code
http://www.swfox.net/sessions.aspx#FLLs_and_the_Visual_FoxPro_API
http://www.swfox.net/sessions.aspx#Using_.NET_in_FoxPro_Applications
http://www.swfox.net/sessions.aspx#Break_It_Down:_Dealing_With_Legacy_Code
http://www.swfox.net/register.aspx


 
Categories: Conference

April 21, 2009
@ 06:38 PM

Check out my article in this month's UT Magazine (April 2009) about interfaces in .NET. I try to explain the how's and why's of them, especially when coming from a loosely-typed language (such as VFP). Hopefully you'll find it useful.


 
Categories: .NET

February 21, 2009
@ 05:36 PM

I just posted a new release of my calendar controls that includes a bunch of new functionality, some more documentation (courtesy of HTML Help Builder from West Wind), along with a few more samples of how this is all supposed to work.

A Bit of History

This all initially started with a small calendar. I initially planned on using Microsoft's ActiveX calendar but realized I needed to be able to select multiple days. Their control really didn't quite work the way I needed it to, so I created my own. I created three different sizes (normal, smaller, and smallest) just because it was easy to do (they're all the same control) and I thought I might need it. Like any project the "hey, wouldn't it be cool if..." features started to grow. In some cases, I needed this functionality for an application anyway, so I went ahead and improved them.

Calendar

The first thing I ended up needing was a drop-down calendar. I already had the calendar portion, so all I needed to do was show and hide it when you clicked on a button next to a text box. So that's basically what I did. It worked well enough, but if the control happened to be at the bottom of a form it was clipped - the initial control was based on a container. I moved this into a form and adjusted the code a bit so it would be able to bleed off the form.

I needed to be able to bind to a date/time field but only display the date portion for data coming from SQL Server, so I named it "rcsDatetimePicker". In hindsight, not a great name. It gives you the impression it lets you view/edit both the date and time portion when in fact it doesn't. At this point I've got a bunch of code which depends on it so it's not being renamed (sorry).

DatePicker

A common use-case for dropdown calendars is to pick a date range. I took an idea from a previous job where you could link two date controls to keep the start date and the end dates from overlapping (ex. the start date can be after the end date). So this was added.

I worked on another project which needed a time control (hours/minutes) so I created one. It seemed like a natural fit to this calendar library so it's been added in. The next logical idea is, "hey, I need a date/time dropdown calendar". The better name for this was already taken, so this was was named rcsCtrDateTimePicker. Yeah, not great, but I didn't have any other ideas.

DateTimePicker

Finally, I just worked on an application which needed an Outlook-style calendar (month view). It seemed like I already had most of the work done from my other calendar, so (I optimistically though) it wouldn't be a big deal to re-purpose it. It actually required a number of changes so it could be nicely resized, display events, etc.

That's basically where the library is today: 3 different sized "static" calendars, a drop-down date w/calendar, a drop-down date/time w/calendar, a time control, plus a large resizable calendar that can have events displayed on it.

LargeCalendar

LargeCalendarMoreEvents

I've tried to provide a few more examples of how these controls can be used along with a help file. It's not as comprehensive as I'd like, but it's a decent start.

Misc. Notes

One thing that's not really covered in the help yet is related to performance of the large calendar when you have a lot of events on it. I ran into this during testing - as you add more events, the calendar navigation became slower and slower. I attempted to optimize this a bit but ultimately ended up modifying my application code to only populate events for the current month plus one month prior and one month following. The calendar shows days from the previous and following months, so if I didn't populate them they'd be missing from the calendar.

You can hook in populating events via the RefreshEvents() event. It fires anytime the calendar needs to be refreshed. I'd suggest just using BINDEVENT to call a form-level method for this event:

BINDEVENT(This.ctrCalendar, "RefreshEvents", This, "RefreshEvents") 

You can determine the current month by looking at the iCurrentYear/iCurrentMonth properties.

Getting Started

I'd suggest playing around with the samples and digging through the help file to get started. The examples cover most of the basic functionality (try clicking on everything and hovering over things, resizing, etc.) and the help file explains some of the class structure.

Let me know what you think.

Links

http://www.west-wind.com/wwHelp/
http://www.rcs-solutions.com/downloads.aspx


 
Categories: VFP

February 14, 2009
@ 12:39 PM

I just uploaded an update for the collapsing comments plug-in for CodeRush/Refactor! I noticed after updating to the latest version (3.2.3) that it suddenly stopped working. After a bunch of digging, and going back and forth with Rory Becker on twitter. He suggested I take a look at manually loading the plug-in via the new Plug-in Manager (DevExpress > Options > Core > Plug-in Manager). I noticed that my plug-in (which is written as a refactoring) had it's Load Type set as "Demand", but most of the other ones were set as "Idle". After a bit of digging I figured out how to change this in my code - it's an attribute in AssemblyInfo. Making this change and recompiling seemed to fix the issue.

 

Links:

http://www.rcs-solutions.com/downloads.aspx
http://twitter.com/rorybecker


 
Categories: CodeRush

February 7, 2009
@ 03:22 PM

I just finished up a report which generates a list of customers whose birthdays fall within a specified date range. I wrote a simple query which did essentially:


DECLARE @startDate datetime
DECLARE @endDate datetime
SET @startDate = '2009-2-15'
SET @endDate = '2009-3-14'

SELECT c.iid,
        c.FirstName,
        c.LastName,
        c.BirthDate,
        c.Address1,
        c.Address2,
        c.City,
        c.State,
        c.ZipCode
   FROM Customers c
  WHERE c.BirthDate BETWEEN @startDate AND @endDate


Of course, that didn't work. That is, unless our customers happened to actually just been born (as of when I wrote this they wouldn't have been even born yet). Hmm....My first thought was maybe joining this to a date table to get the month and day split apart but that idea falls apart pretty quickly so I dismissed it. I'll come back to this idea in a second.

The other simple way to do this is to convert the date to a day of the year, so January 1st is 1, Jan. 2nd is 2, December 31st is 365. SQL Server includes a nice DATEPART() function to make this easy - you can specify that you want the day of the year with it.

So my query was rewritten as:

SELECT c.iid,
        c.FirstName,
        c.LastName,
        c.BirthDate,
        c.Address1,
        c.Address2,
        c.City,
        c.State,
        c.ZipCode
   FROM Customers c
  WHERE DATEPART(dayofyear, c.BirthDate)
BETWEEN DATEPART(dayofyear, @startDate) AND DATEPART(dayofyear, @endDate)


While this one works it's a bit slow. That's not so surprising since it has to use DATEPART on the rows to generate the day of the year in the WHERE clause. My actual code filters the customers a bit more but it was still a fair number of records. Ultimately, since this a summary/reporting table that gets populated and updated nightly I just added another (integer) column to store the precalculated day of the year number.

Surprisingly, this version isn't that much faster - maybe 15% or so. Apparently DATEPART is pretty quick.

It wasn't until after making these changes that I realized I could have added a day of the year column to my date table, done a join then used this column in my WHERE clause. That actually would have been easier if it had occurred to me sooner. I'm guessing performance is probably equivalent, especially since adding the column directly in the table didn't have a huge impact on the speed of the query.


 
Categories: SQL

I've been using CR/R! for a while and one of the simplest changes I've made that makes using it a bit easier is redefining the "Refactor" key - that's the key which causes the refactoring options to pop-up. I've switched mine to just use ` from its default of Ctrl+` - one keypress (it's not like I use the dumb key for much of anything else). There are some many options in CR/R! it's not always easy to find this.

To set it:

  • DevExpress > Options
  • From the side menu select "IDE", then "Shortcuts"
  • In the list you should see "Refactor!", underneath that is the key bound to Refactor.
  • Click on it and on the right hand side change they key binding to whatever you'd like.
  • Hit Apply.

RefactorKey

That all that's needed.


 
Categories: CodeRush

Extension methods were added as a new compiler feature in .NET 3.5. More specifically, that means you can use VS 2008 to use an extension method and then use VS's multi-targeting to run it under .NET 2.0. They're basically a means of tacking on methods onto existing classes or interfaces w/o actually needed to subclass or modify an interface. It's used extensively by (and added because of) LINQ. The methods aren't really part of the class, but the way you use them (and the way they appear in intellisense) make them feel like they're now part of the class. They're essentially static methods scoped to a specific interface or class.

I've been playing around with them a bit and ran into a case where I thought they'd be kind of a cool fit. I've needed to be able to convert a datatable into a comma-delimited file (CSV) so it can easily be opening in something like Excel, or pretty much anything that understands CSV files. I could create a separate class to do this, but it seems like this should be part of the DataTable class. To write an extension method you basically create a static method in a static class and prefix the first parameter with "this". Yep, that's about it.

I wanted it to basically work like this:

DataTable table = myBizObj.DataSet.Tables["SomeTable"];
string csv = table.ToCSV();

Creating the CSV is pretty straightforward - I loop through the column headers to generate the first header row, then I loop through each row in the table, then each item in the ItemArray of the row. I specifically decided to use quotes as delimiters around everything to keep it simple - the rules as to when you can/should include quotes for a CSV are pretty complicated. The only thing I do is escape out embedded quotes in the data by doubling them, ex. " becomes "". As soon as I had it working, I decided to create a few more overloads to let me control whether a header row was required, and the actual delimiter used (ex. instead of comma you could change it to a | pipe for example). Their is some example code in the XML help at the top of the class. In addition, I'm actually using this for a web page so it might be helpful to see what that code looks like:

string results = act.DataSet.Tables[tableName].ToCSV();

string mimeType = RCSSolutions.Web.Utility.DetermineMimeType("csv");

Response.ContentType = mimeType;

Response.AddHeader("Content-Length", results.Length.ToString());

Response.AddHeader("Content-disposition",

                   string.Format("attachment;filename={0}", "DelimitedList.CSV"));

Response.Write(results);

Response.End();

I'm calling out to another helper class which returns the mime type - in this case, all it does is return "application/csv". The above code basically pops open a dialog box with the file name filled in the browser on the client side.

using System;

using System.Collections.Generic;

using System.Data;

using System.Linq;

using System.Text;

 

namespace RCSSolutions.Utility

{

    /// <summary>

    /// <para>Various extension methods.</para>

    /// </summary>

    /// Sample of using ToCSV

    /// <example>

    /// DataTable table = dv.Table;

    /// // Assumes table is a DataTable

    /// string result = table.ToCSV(true);

    /// System.IO.File.WriteAllText(@"C:\sample.csv", result);

    /// System.Diagnostics.Process proc = new System.Diagnostics.Process();

    /// proc.StartInfo.FileName = @"C:\sample.csv";

    /// proc.StartInfo.UseShellExecute = true;

    /// proc.Start();

    /// </example>

    public static class Extensions

    {       

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.      

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table)

        {

            return ToCSV(table, ",", true);

        }

 

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <param name="includeHeader">true - include headers<br/>

        /// false - do not include header column</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table, bool includeHeader)

        {

            return ToCSV(table, ",", includeHeader);

        }

 

        /// <summary>

        /// Converts the passed in data table to a CSV-style string.

        /// </summary>

        /// <param name="table">Table to convert</param>

        /// <param name="delimiter">Delimiter used to separate fields</param>

        /// <param name="includeHeader">true - include headers<br/>

        /// false - do not include header column</param>

        /// <returns>Resulting CSV-style string</returns>

        public static string ToCSV(this DataTable table, string delimiter, bool includeHeader)

        {

            StringBuilder result = new StringBuilder();

 

            if (includeHeader)

            {

                foreach (DataColumn column in table.Columns)

                {

                    result.Append(column.ColumnName);

                    result.Append(delimiter);

                }

 

                result.Remove(--result.Length, 0);

                result.Append(Environment.NewLine);

            }

 

            foreach (DataRow row in table.Rows)

            {

                foreach (object item in row.ItemArray)

                {

                    if (item is System.DBNull)

                        result.Append(delimiter);

                    else

                    {

                        string itemAsString = item.ToString();

                        // Double up all embedded double quotes

                        itemAsString = itemAsString.Replace("\"", "\"\"");

 

                        // To keep things simple, always delimit with double-quotes

                        // so we don't have to determine in which cases they're necessary

                        // and which cases they're not.

                        itemAsString = "\"" + itemAsString + "\"";

 

                        result.Append(itemAsString + delimiter);

                    }

                }

 

                result.Remove(--result.Length, 0);

                result.Append(Environment.NewLine);

            }

 

            return result.ToString();

        }

    }

}


 
Categories: .NET | C#

December 23, 2008
@ 10:12 PM

I was trolling Digg tonight and ran across this article about finding rare songs on YouTube. I hadn't really thought about it but I had found some great Pink Floyd videos on there a while back. I've had a song (not Pink Floyd) knocking around in my brain for a while that I was never able to identify; all I could remember was "suckerpunch". So I typed "suckerpunch song" into the search on YouTube and bang, there it was. Actually, after hearing this again (besides realizing it was from around 1993) was how much this sounded like Nine Inch Nails, March of the Pigs (released around the same time). OK, it doesn't quite match up as well as it did in my head (or as well as this), but whatever. It's got the same sort of feel.

That got me thinking about when I saw Pink Floyd at the Pontiac Silverdome; I was trying to figure out what year I went. This, of course, got me thinking about the first concert I ever saw: Iron Maiden at Joe Louis Arena. That led me back to YouTube. And Guitar Hero.

The internets is cool. And a huge waste of time. But mostly cool.

Links:

http://digg.com
http://news.cnet.com/8301-13772_3-10125016-52.html?part=rss
http://www.youtube.com
http://www.youtube.com/watch?v=M_bvT-DGcWw
http://www.youtube.com/watch?v=plBna98XZNQ
http://www.youtube.com/watch?v=U2LwEQFK3qc
http://www.youtube.com/watch?v=7xNQZHuAQJ8
http://ourworld.compuserve.com/homepages/PFArchives/tourdate.htm
http://www.maidenfans.com/imc/index.php?url=tour06_sit/dates06_sit&link=tours&lang=deu
http://www.youtube.com/watch?v=AUOpUqni0_g
http://www.youtube.com/watch?v=e39D8VBQ4sw

Bonus Track (just because this is a great song):

http://www.youtube.com/watch?v=k5JkHBC5lDs


 
Categories: Other

I recently added a maintenance form to our website which allows a user to add and delete entries to a list of banner ads stored in a simple XML file. Previously we've just been maintaining them manually by editing the XML directly and copying the associated banner images into a folder on the website. When you delete an ad, I decided to NOT delete the associated image since they may be reused (and I wanted to avoid forcing the user to upload the image again). However, we'd still like to periodically clean out this folder and "archive" the images so they're not cluttering up the selection screen.

I basically needed some code which would get me a list of files in the banner images folder which were not referenced in my banner XML file. It can be kind of clunky to iterate through XML but they've made it much easier with the introduction of LINQ. I fired up LINQPad (which, BTW, is an AWESOME free tool for testing out LINQ code) and tried out a few ideas. As a side note, it looks like Intellisense is now available if you purchase a copy of LINQPad.

http://www.linqpad.net/

I started with querying the filesystem to get a list of files:

  

DirectoryInfo info = new DirectoryInfo(@"X:\inetpub\wwwroot\images\banner");

FileInfo[] files = info.GetFiles();

 

files.Dump();

 

.Dump() is an extension method available in LINQPad which dumps out the results of the query (we haven't actually used LINQ yet to do anything).

Here's what it looks like:

FileInfoLinq

You might notice that Directory contains a DirectyInfo element. If you click on the down arrow it will expand out these values as well.

So I now had a list of files, I wanted to then get a list of images referenced in my banner file. Here's the format of the XML file:

<News>   
   <NewsItem>
       <Title>Supertooth3-banner.gif</Title>
       <Image>/images/banner/Supertooth3-banner.gif</Image>
       <Height>183</Height>
       <Link>/PortalView.aspx?navto=/Supertooth3-banner.gif</Link>
       <Date>July, 19th, 2003</Date>
       <Target></Target>
   </NewsItem>   

  

 

I haven't really been using Title for anything besides the name of the image file, so I was able to take a bit of a shortcut here and use it for my comparison. To pull out the list of images used in the XML, I wrote this query:

XDocument doc = System.Xml.Linq.XDocument.Load(@"X:\inetpub\wwwroot\adv.xml");

doc.Dump();

 

var news = from item in doc.Descendants("Title")

           orderby item.Value

           select item.Value;

news.Dump();

 

Which produces this:

XmlTitlesLinq

I noticed that the banner images folder contained a bunch of other files that I really didn't want to consider for filtering, so I needed to narrow my query to files that had specific extensions. C# doesn't really have a direct equivalent for INLIST, but we can do this a slightly different way for the same effect.

First I define an array of valid extensions, then (inside the where clause of the LINQ query) I check to see if this list of file types contains the filetype of the file I'm currently evaluating. It's a bit backwards, but it's simple and it works.

string[] fileTypes = { ".jpg", ".gif", ".png" };

var imgFiles = from file in files

               where (fileTypes.Contains(file.Extension))

               orderby file.Name

               select file.Name;

 

imgFiles.Dump();

 

Now I've got a list of files from my XML and a list of files from the banner images folder. I want to get a list of files from the banner images folder that aren't in the XML list. I do this via a final query:

var extra = from singleFile in imgFiles

            where !(news.Contains(singleFile))

            select singleFile;

extra.Dump();   

This returns my extra files. Now I can just use this list to move my images into an archive folder periodically.

If I put it all together, I end up with this:

 

XDocument doc = System.Xml.Linq.XDocument.Load(@"X:\inetpub\wwwroot\adv.xml");

DirectoryInfo info = new DirectoryInfo(@"X:\inetpub\wwwroot\images\banner");

FileInfo[] files = info.GetFiles();

doc.Dump();

files.Dump();

 

var news = from item in doc.Descendants("Title")

           orderby item.Value

           select item.Value;

news.Dump();

string[] fileTypes = { ".jpg", ".gif", ".png" };

var imgFiles = from file in files

               where (fileTypes.Contains(file.Extension))

               orderby file.Name

               select file.Name;

 

imgFiles.Dump();

 

var extra = from singleFile in imgFiles

            where !(news.Contains(singleFile))

            select singleFile;

extra.Dump();   

Links:

http://www.linqpad.net/


 
Categories: .NET | C# | LINQ

November 26, 2008
@ 08:50 PM

I thought this was an interesting question that has come up a couple of times in the last few days over on the Universal Thread. In VFP you can create a subclass of a form, customize it, then configure VFP to use this subclass as the "template" for any new forms you create (by going into Tools > Options > Forms and setting the base class).

The question was, how do I do this in .NET?

It's pretty easy - create your form and add any controls, methods, properties, etc. that you want. Then go to File > Export Template. An Export Template Wizard will open. Change the selection to an "Item template" and click Next.

Export Template Wizard

 

On the next screen put a checkmark next to the item(s) you want included in the template. If you have other dependencies (like external classes) you can also select them here. Then click Next again.

Export Template Wizard Select Item to Export

Now you can select any external references you want to include. For example, if you created a project which includes a set of base controls that you used on your form, you may want to select them here (so when you use this template these references will automatically get added to your project). Click Next.

Export Template Wizard Select Item References

Finally you can select an icon that is associate with this template, enter the template name, description, and it's output location. I'd suggest leaving the "Automatically import the template into Visual Studio" option checked. If you don't like the output location, unfortunately you can't change it here. You have to change it via Tools > Options > Projects and Solutions. Finally click Finish.

Export Template Wizard Select Template Options

At this point, when you do an "Add New Item" you should be able to scroll to the bottom of the templates and see "My Templates" - the new template you created should exist there.

Although I showed this for a WinForms application, this can actually be used with any class (and for ASP.NET applications). For example, I have a base business object class I use. Every time I create a new one I just select a template based on a subclass of it to create the new one.


 
Categories: .NET | Visual Studio

I received this error on a page which had previously been working. That morning I had updated our site, so I was expecting some issues, but this error doesn't really tell you much. We have a maintenance screen which displays a list of records in a grid. When you click on an edit link the grid converts into an "in place" editor (a UI metaphor I thought I'd like when I initially put the form together but which, as it turns out, I really hate).

A user had reported that when they clicked on a button which saves this record that it wasn't closing and updating the list. We are using Telerik web controls for most of the site so I figured it had to do with them since I updated a number of pages, including our master page, to start using the RAD AJAX version of the controls instead of their previous version. It seems this error was being caused because I had added an instance of the RadAjaxManager control to the master page, and I already had an instance of a AjaxManager (older version) on the content page itself. Both managers were conflicting with one another, which caused this error.

All I needed to change was the "RadAjaxManager" markup code to a "RadAjaxManagerProxy" and that resolved this particular error.


 
Categories: ASP.NET

November 8, 2008
@ 10:19 AM

I needed to sign back up for online access to one of my bank accounts. I used to have this all automated through Quicken but at some point it broke and I never seemed to get around to fixing it. I couldn't remember the account password so I requested it to be changed. They had a cool step where they had me select which phone number I had registered with the account would be called. As soon as I hit "Next" they (well, their automated system) was calling. They wanted me to confirm the fact that I was expecting the call and to enter a code which was shown on the screen. As soon as I did that it allowed me to continue on to change my password.

That was pretty cool - a pretty painless way of ensuring I'm really who I say I am. Imagine how disappointed I was when I started typing in my new password:

Bank Password

Really? No special characters and I'm limited to 12 characters for access to my bank account? (sigh). My LinkedIn account has a more secure password than this. Lame.


 
Categories: Soapbox