navigation
 Thursday, May 31, 2007

A higher-order function is defined as a function that returns a function as a result. Higher-order functions are common in the world of functional programming, but have only recently started to become more mainstream. As of C# 2.0, they are starting to become part of the language. A perfect example of their use would be with the generic List<T>.FindAll() method, which takes a Predicate<T> as an argument. A Predicate<T> is a delegate, which is a strongly typed method reference. One way to search for all the items in a list is to use anonymous delegates. For example, given a list of Falafel employees:

List<Falafel> falafels = new List<Falafel>();
falafels.Add( new Falafel( "Lino", "Tadros" ) );
falafels.Add( new Falafel( "John", "Waters" ) );
falafels.Add( new Falafel( "Noel", "Rice" ) );
falafels.Add( new Falafel( "Adam", "Anderson" ) );
falafels.Add( new Falafel( "Xavier", "Pacheco" ) );
falafels.Add( new Falafel( "Adam", "Markowitz" ) );
falafels.Add( new Falafel( "Mike", "Dugan" ) );
falafels.Add( new Falafel( "Bary", "Nusz" ) );
falafels.Add( new Falafel( "Rick", "Miller" ) );
falafels.Add( new Falafel( "Mike", "Saad" ) );
falafels.Add( new Falafel( "Eric", "Titolo" ) );

You could search for all employees whose name starts with "A" like this:

falafels.FindAll( delegate( Falafel item ) { return item.FirstName.StartsWith( "A" ); } )

Output:
Adam Anderson
Adam Markowitz

However, if you wanted to perform another search for all employees whose name starts with "M", you'd have to write an entirely different anonymous delegate. That's where higher-order functions can help. Let's create a higher-order function that will return a delegate that searches for Falafels whose first name starts with a string we pass as a parameter:

public static class Predicates
{
  public static Predicate<Falafel> FirstNameStartsWith( string s )
  {
    return delegate( Falafel item ) { return item.FirstName.StartsWith( s ); };
  }
}

Now we can search for employees whose name starts with any letter we want:

falafels.FindAll( Predicates.FirstNameStartsWith( "A" ) );
falafels.FindAll( Predicates.FirstNameStartsWith( "M" ) );

Output:
Adam Anderson
Adam Markowitz

Mike Dugan
Mike Saad

But the fun doesn't stop there! If you define a set of primitive Predicates, you can define more complex Predicates as a combination of the simpler ones. Here is how to define higher-order functions that take a list of Predicates and returns a Predicate that returns the result of evaluating each of them and combining the result with the logical AND or OR operator:

public static Predicate<Falafel> And( params Predicate<Falafel>[] predicates )
{
  return delegate( Falafel item )
  {
    foreach ( Predicate<Falafel> predicate in predicates )
      if ( !predicate( item ) )
        return false;
    return true;
  };
}

public static Predicate<Falafel> Or( params Predicate<Falafel>[] predicates )
{
  return delegate( Falafel item )
  {
    foreach ( Predicate<Falafel> predicate in predicates )
      if ( predicate( item ) )
        return true;
    return false;
  };
}

Using these, we can create a single Predicate that searches for all Falafels whose first name starts with "A" or "R" and whose last name starts with "M":

Predicate<Falafel> predicate = Predicates.Or( Predicates.FirstNameStartsWith( "A" ), Predicates.FirstNameStartsWith( "R" ) );
predicate = Predicates.And( predicate, Predicates.LastNameStartsWith( "M" ) );
falafels.FindAll( predicate );

Output:
Adam Markowitz
Rick Miller

Higher-order functions are a powerful abstraction, and they're only going to become more common and easier to write with C# 3.0 lambda expressions, so give them a try and see how they can help make your code more concise and expressive.

posted on May 31, 2007  #    by Adam Anderson  Comments [0]
 Wednesday, May 23, 2007

Visual Studio comes with some handy (and some not-so-handy) code snippets, but for some reason there isn't one for declaring a method. It isn't that big of a deal, but after a while you might start resenting finishing your method header, then having to type Enter, {, Enter, }, Up, Enter to start the method body. Here's a snippet that will automatically put an open and closing brace after your method declaration, with the cursor ready to go in between:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>method</Title>
      <Shortcut>m</Shortcut>
      <Description>Code snippet for methods</Description>
      <Author>Adam Anderson</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>method-modifiers</ID>
          <ToolTip>Method modifiers</ToolTip>
          <Default>public</Default>
        </Literal>
        <Literal>
          <ID>return-type</ID>
          <ToolTip>Return type</ToolTip>
          <Default>void</Default>
        </Literal>
        <Literal>
          <ID>member-name</ID>
          <ToolTip>Method name</ToolTip>
          <Default>Name</Default>
        </Literal>
        <Literal>
          <ID>param-list</ID>
          <ToolTip>Parameter list</ToolTip>
          </Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
        <![CDATA[$method-modifiers$ $return-type$ $member-name$( $param-list$ )
{
$end$
}]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

posted on May 23, 2007  #    by Adam Anderson  Comments [0]
 Tuesday, May 15, 2007

There's a fascinating little article "Create Advanced Web Applications With Object-Oriented Techniques" by Ray Djajadinata that delves into how JavaScript implements objects, inheritance, anonymous methods, and even a bit about simulating private properties and namespaces.  This may be relevant if you want greater depth in AJAX, particularly the Microsoft flavor ASP.NET AJAX.  There's a sidebar (by Bertrand Le Roy) about the ASP.NET AJAX OOPS implementation and use of JavaScript to add reflection and other .NET familar constructs including properties, events, enumerations and interfaces.

posted on May 15, 2007  #    by Noel Rice  Comments [0]
 Monday, May 14, 2007

This is one of those little things I'm looking forward to getting out of C# 3.0: inferred types. I've always throught to myself, "I just declared the variable to be that type, can't you figure it out without me spelling it out for you, C# compiler?" Well, the compiler can't figure it out yet, but here's a little snippet I cooked up so at least I don't have to type the type name twice:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>var</Title>
      <Shortcut>var</Shortcut>
      <Description>Code snippet for declaring and initializing a variable with a type cast</Description>
      <Author>Adam Anderson</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>Variable type</ToolTip>
          <Default>Type</Default>
        </Literal>
        <Literal>
          <ID>name</ID>
          <ToolTip>Variable name</ToolTip>
          <Default>Name</Default>
        </Literal>
        <Object>
          <ID>value</ID>
          <ToolTip>Initial value</ToolTip>
          <Default>Value</Default>
          <Type>System.Object</Type>
        </Object>
      </Declarations>
      <Code Language="csharp">
        <![CDATA[$type$ $name$ = ($type$) $value$;
        $end$]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

To install, copy and paste the above XML into a file and save it with a .snippet extension to your code snippets directory (My Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets). To use, simply type "var" and press Tab.

Now as you type the type name, it will be duplicated for you in the type cast.

Every little annoyance eliminated is productivity gained. Enjoy!

posted on May 14, 2007  #    by Adam Anderson  Comments [0]
 Monday, May 07, 2007

We recently decided to use Developer Express XtraReports for one of our projects. While it's an impressive product with rich functionality, its design-time support within a web project definitely isn't as robust as it is within a windows project. After some trial and error, I discovered the trick to getting the designer preview tab to work with a parameterized query. Here's how it's done:

  1. In a web project, add a new XtraReport
  2. With the XtraReports designer open, double-click on a DataAdapter. If no DataAdapters are visible in your toolbar (none were in mine by default), you'll have to add them to the toolbar manually.
  3. Configure the DataAdapter using the wizard
  4. In the property grid, navigate to the DataAdapter's SelectCommand | Parameters property. Use the Parameters dialog to set a default value for each parameter. This will enable the report to execute the command at design-time.
  5. Select "Generate DataSet" from the DataAdapter's context menu. In the dialog that appears, make sure to check the box that says "Add this dataset to designer."
  6. The report's DataSource, DataMember, and DataAdapter properties should already be set correctly. Click on the report and examine the properties to confirm.
  7. Try adding a few fields to the detail band of the report, then click the preview tab. After a short delay, the preview should appear!

This approach uses DataAdapter classes directly. The default adapter created by Visual Studio if you create the DataSet first and then add a table will be a TableAdapter. TableAdapters will not work with this approach, because they have no facility to set default parameter values at design time. Unfortunately, the only adapters that appear in the XtraReports' DataAdapter property editor are TableAdapters. However, if you click in the grid and start typing the name of your DataAdapter, the property grid will locate it and assign it to the property correctly.

posted on May 7, 2007  #    by Adam Anderson  Comments [0]
 Sunday, May 06, 2007

I recently ran into an unexpected behavior of SSRS while writing a complex report. The report required various calculations that would refer to specific previous groups and details, and I had decided to solve the problem by writing a custom report function that would evaluate on each detail row, saving the information I would need later in a dictionary. My solution worked fine, as long as my custom calculation in a group footer didn't depend on the contents of that group's details. Upon further investigation, I learned something very interesting about the order in which SSRS evaluates group headers, footers, and details...

Here is how to observe the behavior for yourself: create a stored procedure like this one, that generates some simple test data:

CREATE PROCEDURE dbo.HundredRows
AS
SET NOCOUNT ON

create table #result (
id int,
grp int
)

declare @id int
set @id = 1

while @id <= 100
begin
insert #result
values ( @id, ( @id - 1 ) / 5 )

set @id = @id + 1
end

select *
from #result

This will return a result set whose id column increments in steps of one from 1 to 100, and whose grp column increments in steps of one for every five rows. Next, create a simple report layout with a table, showing the values of each column and grouping by the grp column. In the group header and footer, include the same column references. Next, add this custom code:

Dim eval_order As Integer = 0

Public Function show_eval_order() As String
  eval_order = eval_order + 1
  Return eval_order.ToString()
End Function

Display the result of this function in the group header, footer, and detail rows. Your layout should look like this:

Once you have the report set up, click on the preview tab to see the surprising results:

I've only shown the first two groups here, but notice what has happened! The order column clearly indicates that the group header and footer are both evaluated before the details in between! By looking at the value of the id column in the footer, we can see that the the group's header and footer rows are printed while the "current" row in the dataset is still positioned on the first row in the group.

While this is interesting, it isn't very important as long as you stick to using SSRS's built-in aggregation functions. It is only when you attempt to "roll your own" by saving the dataset in your own storage for later reference that you might run into trouble. In my case, I used the following workarounds:

  1. Move calculations that rely on the details having been traversed from the group footer to the following group's header. It's clunky and less intuitive, but that's what SSRS has forced upon us.
  2. For the final group, move the calculation out of the table entirely, and put it into textboxes just below the table. While there is no way to tell SSRS to evaluate the textboxes after it evaluates the table, it does so at least for the 2005 version.

In summary, it sure would have been nice if SSRS would have evaluated group headers and footers after it evaluated the details that each group contains, but since we have clearly demonstrated that it doesn't, we now know what we will have to do in order to make custom report code produce the output we want: by putting those custom calculations into the following group's header, and by putting the final footer calculation outside the table entirely.

posted on May 6, 2007  #    by Adam Anderson  Comments [0]
 Wednesday, May 02, 2007

We recently completed a self-paced tutorial for Telerik RadControls.

You can download the self paced tutorial from the Telerik site at:

http://www.telerik.com/support/self-paced-tutorial.aspx

The tutorial addresses the entire suite of RadControls, AJAX, client-side scripting, and custom data-binding techniques.

posted on May 2, 2007  #    by Noel Rice  Comments [0]

If you need to monitor your transactional replication with a custom monitoring service, Microsoft has provided some useful tools to help. Recently I was having trouble reliably monitoring my replication, and then I discovered this page.

 

http://msdn2.microsoft.com/en-us/library/ms146951.aspx

 

If you’re using transactional replication there is no better way to monitor its health than using your own tracer token. This is just like inserting a tracer token using the replication monitor utility in SQL Server Management Studio.

 

First you need to create a connection to the server.

 

   server = new ServerConnection(sci); 

 

then create a TransPublication object.

 

    TransPublication transPublication = new TransPublication(publicationName, publicationDBName, server);

 

Call LoadProperties of the new object to make sure that all publications and subscriptions are loaded.

 

   transPublication.LoadProperties(); 

 

Then post the tracer token and call refresh to send it on its way. You need to save the ID of the token so that you can clean it up later.

 

   id = transPublication.PostTracerToken();
   transPublication.Refresh();
 

 

Now that the tracer token is on its way we need to create a publication monitor to look for its return. You have to go through a couple of layers to get to it.

 

   Microsoft.SqlServer.Replication.ReplicationMonitor monitor =

      new Microsoft.SqlServer.Replication.ReplicationMonitor(server);
   PublisherMonitor pub = monitor.PublisherMonitors[publisherMonitor];
   PublicationMonitor publicationMonitor = pub.PublicationMonitors[publicationDBName, publicationName];

Now we need to enumerate all of the tokens in the publication. You must call LoadProperties to refresh this list.

 

   publicationMonitor.LoadProperties();
   ArrayList tokens = publicationMonitor.EnumTracerTokens();
 

 

You can cast the items in the array list to a TracerToken type to find the token we sent with the ID we saved earlier.

 

   TracerToken token = null;
   foreach (TracerToken t in tokens)
   {
      if (t.TracerTokenId == tokenID)
      {
         token = t;
         break;
      }
   }
 

 

Now that we have our token we need to enumerate the tracer token history with this call.

 

   DataSet tth = publicationMonitor.EnumTracerTokenHistory(token.TracerTokenId); 

 

This returns a dataset that you need to parse through to get the data we are interested in. These include distributor latency, subscriber latency, and overall latency. If these values are blank, then the token has not returned yet. You need to then enumerate the tokens and check again. When the token has returned you then need to cleanup. A simple call will do this for us.

 

   publicationMonitor.CleanUpTracerTokenHistory(tokenID);

 

If any part of the replication fails for any reason, the token will fail to return and you know you have a problem.

posted on May 2, 2007  #    by Bary Nusz  Comments [0]
 Tuesday, May 01, 2007

You can support docking in your web applications using Telerik's new control suite "Prometheus".  Prometheus is completely redesigned to use Microsoft's ASP.NET Ajax.  The Prometheus docking controls make it easy to define objects that may be dragged and areas where objects may be dragged to.  With docking support you can create web portal sites, "PageFlake" style web pages (where the user can dynamically add controls and drag them around on the page), or even "post-it notes" can be added to the page.  The current state-of-play is that the controls are in beta and have a few quirks, but the performance is very responsive and the look and feel is also quite good.

To use Prometheus "RadDock" controls first download and install the Microsoft ASP.NET Ajax extensions at http://ajax.asp.net/, then get the free Prometheus beta download at: http://www.telerik.com/products/aspnet-prometheus/download.aspx.  Once installed, create a new project type "ASP.NET AJAX-Enabled Web Application".  BTW, if you try to use the standard ASP.NET web application you will get really interesting results.

Your toolbox will have the new AJAX extension controls, including "ScriptManager".  ScriptManager is the workhorse of Microsoft's ASP.NET Ajax that registers client side scripts that enable AJAX functionality. The ScriptManager is automatically placed on the default web page so you don't need to do anything further there.

Also in the toolbox are the new Prometheus controls.  The three you need for drag and drop support are:

  • RadDock is the container for text or other controls that need to be dragged on the web page.
  • RadDockZone defines an area on the screen where a RadDock can dropped onto.
  • RadDockLayout can contain a number of RadDockZone controls so you can set the skin for everything at once.  RadDockLayout also has a property StoreLayoutInViewState that can be used to persist the RadDock locations across multiple postbacks.

To test these controls drop a RadDockLayout, two RadDockZones within the RadDockLayout and RadDock controls in each of the RadDockZones. 

How about adding content to the RadDock? 

  • Use the Radock Text property for simple text only that doesn't involve any other controls.
  • Create your own ITemplate implementation class and set the RadDock ContentTemplate property to that class in the code behind.
  • Add to the ContentTemplate property markup.  At this stage of development I don't see a smart tag or other UI assistance so instead add a ContentTemplate tag and add controls within the tag.

For example we could add another new Prometheus control "RadColorPicker":

<ContentTemplate>
  <telerik:RadColorPicker ID="RadColorPicker1" runat="server" Preset="Standard">
  </telerik:RadColorPicker>
</ContentTemplate>

To finish up we set the Skin property of RadDockLayout to "Longhorn".  If you've used the current version of RadDock you're used to adding various skin files to the project.  Not with the Prometheus version where the skins are built-in and you can choose the Skin property value from a drop down list.  Finally you can set the title bar text for each RadDock using the Title property.

When you run the Prometheus version of the docking controls you should experience snappy responsiveness and a very respectiable UI.  Try downloading Prometheus and retrofit some part of your current web application to support docking.  Enjoy!

Note: if you want to learn Telerik RadControls from the ground up, check out the Falafel-authored, self-paced tutorial at http://www.telerik.com/support/self-paced-tutorial.aspx and download the sample projects from our community download site at http://www.falafel.com/community/files/Default.aspx.

posted on May 1, 2007  #    by Noel Rice