navigation
 Tuesday, September 05, 2006

I recently ran into a problem with a large DataSet when I set the EnforceConstraints to true. It gave me the error “Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.” without any clue as to where to look or what to do. Googling the problem, I came across a blog by Dave Lloyd with a good method to figure out exactly where the error is. The only problem was the example code was Dimmed. Naturally I un-Dimmed the code and put it in a proper C# format. I then encapsulated it into a nice little static function that returns a NameValueCollection loaded with all of the relevant error info. The info returned tells you what table, what row/column, and what the constraint is.

private static NameValueCollection BuildDataSetErrorInfo(DataSet dataSet)     
        {     
            NameValueCollection errorInfo = new NameValueCollection();     
            errorInfo.Add("DataSetName: ", dataSet.DataSetName);     
            foreach (DataTable table in dataSet.Tables)     
            {     
                DataRow[] rows = table.GetErrors();     
                if ((rows != null) && (rows.Length > 0))     
                {     
                    errorInfo.Add("Table: ", table.TableName);     
                    foreach (DataRow row in rows)     
                    {     
                        errorInfo.Add("Row Error: ", row.RowError);     
                        DataColumn[] cols = row.GetColumnsInError();     
                        if ((cols != null) && (cols.Length > 0))     
                        {     
                            foreach (DataColumn col in cols)     
                            {     
                                errorInfo.Add("Column: ", col.ColumnName);     
                                errorInfo.Add("Column Error: ", row.GetColumnError(col));     
                            }     
                        }     
                    }     
                }     
            }     
            return errorInfo;     
        }   
 
posted on September 5, 2006  #    by Bary Nusz  Comments [0]
 Wednesday, August 16, 2006

If you add an item using the indexer, like this:

Cache["TestItem"] = value;

The item is added to the cache with no expiration policy and a normal priority. As a result, the item will stick around indefinitely.
We can help the cache decide which items to toss out of memory by specifying an expiration policy and/or a priority:

Cache.Insert("TestItem", value, null, Cache.NoAbsoluteExpiration,
  TimeSpan.FromMinutes(20), CacheItemPriority.Normal, null)

Above, I gave the item a 20 minute sliding expiration. This means each time the item is accessed, its 20 minute lease on life is renewed.
I could have told it to expire after exactly 20 mins, no matter how many times it is accessed by setting an absolute expiration instead:

Cache.Insert("TestItem", value, null, DateTime.Now.AddMinutes(20),
  Cache.NoSlidingExpiration, CacheItemPriority.Normal, null)

And to really take control of the scavenging mechanism, you can change the priority of items added to the cache. Lower priority, means it is removed first when system resources are running low. The values range from "Low" to "NotRemovable". See the CacheItemPriority type's documentation for all of the values.

You will also notice that the Cache has an "Add" method. If you choose to use the Add method, adding a key that already exists in the cache will result in an exception, while doing the same with the Insert method will overwrite it. Setting a value using the indexer is equivalent to this call:

Cache.Insert("TestItem", value, null, Cache.NoAbsoluteExpiration,
  Cache.NoSlidingExpiration, CacheItemPriority.Normal, null)

posted on August 16, 2006  #    by Mike Dugan  Comments [0]
 Sunday, August 13, 2006

For those who know me, it will come as no surprise that the first mobile web site that I will cover is a weather site. Although there are many weather sites, few are worth mentioning. http://mobile.wunderground.com/ is absolutely the best weather site for your mobile device. If you’ve been inside all day and hear distant thunder, you can quickly pull up your local radar, check for severe weather warnings, and your forecast. All of these pages are stripped down to just the facts. For more serious weather nerds, radar animations, storm tracks, and a quick view of all severe weather in the nation are available. Mark this site now!

posted on August 13, 2006  #    by Bary Nusz  Comments [0]
 Monday, July 24, 2006

As an application developer, I often need to generate scripts for mutiple database objects, each in its own file, with both a DROP and a CREATE statement. In SQL Server 2000, there was a robust set of scripting options to choose from which allowed exactly this kind of use. However, in SQL Server 2005, these options have vanished. All selected objects get put into a single script file, and there is no way to generate DROP and CREATE in a single script. Some options can be accessed by choosing the Tasks | Generate Scripts... menu item at the database level, but they don't provide the desired functionality, and the wizard itself is cumbersome to navigate.

In response to this loss of functionality, Bill Graziano wrote a utility that mimics these commonly-used options of SQL scripting. The original blog, which contains links to an installer as well as source code, can be found here.

posted on July 24, 2006  #    by Adam Anderson  Comments [0]
 Monday, June 05, 2006

A lot has been written about the merits of multiple narrow indexes versus single larger compound indexes. This blog by Grant Fritchey yields juicy food for thought on that very topic, backed by some very thorough testing with real-world data.

posted on June 5, 2006  #    by Adam Anderson  Comments [0]
 Wednesday, May 31, 2006

There is a cool new feature in ASP.NET 2.0 that allows you to embed resources into your server side assemblies and have your web controls request these resources automatically. This is especially handy when you want to deploy a new control. No longer do you have to find just the right spot to place the JavaScript and image files that your control depends on. 

Microsoft already uses this technique with its validators. The JavaScript needed for client side validation is embedded in one of the .NET assemblies on the server. If you were to view the source of any web page that uses a validator in ASP.NET 2.0, you might see something like this:

<script src="/MyWebSite/WebResource.axd?d=68d8KT0ikvX6J4c8Z8zwvfZXzPdyyYYY8TuccizWlCePFWz&t=632847500868593750" type="text/javascript"></script>

This is a request to a new HttpHandler, WebResources.axd, for the necessary JavaScript. The first parameter, ‘d’ is an encrypted identifier telling the handler which resource it needs. The ‘t’ parameter is an encrypted timestamp, used to determine if the resource has changed.

Looks pretty simple right?

Well, lets see how easy it is for you to use this technique. Lets try to create a control that has its JavaScript embedded as a resource. For this example, I am going to use a useful script that buffers key presses and matches an entire word in a dropdownlist instead of just the first character. (Thanks to Jonathan Cogley at ASP Alliance for the original script: http://authors.aspalliance.com/thycotic/articles/view.aspx?id=3)

First, lets open up or create a new web site in Visual Studio 2005 and then add a new Web Control Library project to it. After adding the project, remember to add a reference to it from our web site.  This new assembly will contain all of the elements of our control and our web site has to know about it to use it.

Next, lets add a new class that inherits from DropDownList:

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;


 

namespace WebControlLibrary1
{
    public class KeyedDropDownList : DropDownList
{
        private bool _caseSensitive = false;

        public KeyedDropDownList(){}

    
     public bool CaseSensitive
     {
     get
     {
     return _caseSensitive;
     }
     set
     {
     _caseSensitive = value;
     }
     }
    }
}

I have also added a property “CaseSensitive” which will be passed to the script to allow us to turn on and off case sensitivity when matching strings in our list.

Now add a new a JScript file and examine the properties. To embed this file as a resource the Build Action must be set to 'Embedded Resource'.  After setting the build action,  feel free to copy this code into the file or substitute JavaScript of your own:

function KeyedDropDownList_onkeypress(dropdownlist,caseSensitive) 
{
// check the keypressBuffer attribute is defined on the dropdownlist
var undefined;
if (dropdownlist.keypressBuffer == undefined)
   {
dropdownlist.keypressBuffer = '';
}
   // get the key that was pressed
var key = String.fromCharCode(window.event.keyCode);
dropdownlist.keypressBuffer += key;
  if (!caseSensitive)
   {
// convert buffer to lowercase
dropdownlist.keypressBuffer = dropdownlist.keypressBuffer.toLowerCase();
}
  // find if it is the start of any of the options
var optionsLength = dropdownlist.options.length;
for (var n=0; n < optionsLength; n++)
{
var optionText = dropdownlist.options[n].text;
if (!caseSensitive)
     {
optionText = optionText.toLowerCase();
  }
if (optionText.indexOf(dropdownlist.keypressBuffer,0) == 0)
     {
dropdownlist.selectedIndex = n;
return false; // cancel the default behavior since
// we have selected our own value
     }
}
// reset initial key to be inline with default behavior
dropdownlist.keypressBuffer = key;
return true; // give default behavior
}

Next,  you must add an attribute to the assemblyinfo.cs file to reference the embedded resource:

[assembly: System.Web.UI.WebResource("WebControlLibrary1.JScript1.js", 
"text/javascript")]

You will notice that the reference to the JScript file is fully qualified. You must do this using the project's default namespace, not just any old namespace in the assembly. You can see this  by right clicking on the project and viewing the properties. I should also mention that we intentionally left out an optional boolean parameter named 'PerformSubstitution'. By default 'PerformSubstitution' is off, and you should turn it on if the referenced resource accesses other embedded resources. An embedded style sheet that defines some style using an embedded image is a good example of when to set PerformSubstitution to true.

Now, instead of registering the script block with the necessary JavaScript ourselves, we will register a request to get the script block from our  assembly.  Thanks to the new ClientScriptManager in ASP.NET 2.0, this is  very easy.  We will first override the OnInit method of our KeyedDropDownList class and then  get a reference to this manager to do most of our work.

protected override void OnInit(EventArgs e)    
{
base.OnInit(e);
ClientScriptManager cs = Page.ClientScript;
Type rsType = this.GetType();
cs.RegisterClientScriptInclude("MyScript",
cs.GetWebResourceUrl(rsType,"WebControlLibrary1.JScript1.js"));
}

The last piece of coding is very simple.  Just attach  the onkeypress event of our control to our custom JavaScript function.  Although in this example we have not used the ViewState to track our lone property,  we might want to do that or add more properties that can be passed to the JavaScript function.  So here I overrode the OnLoad method to add the attribute to our webcontrol. By the time the OnLoad event is fired, the ViewState will have been  loaded.

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.Attributes.Add("onkeypress",
"return KeyedDropDownList_onkeypress(this," +
_caseSensitive.ToString().ToLower() + ")");
}

If all goes well, we should be able to now use this control on any form in our web app and the necessary JavaScript will automatically accompany it wherever it goes. I should also point out that when debugging, the JavaScript is not cached, it is downloaded each time. When debugging is off, the JavaScript is cached on the client automatically. 

I have  included the markup for the test page that registers and uses this new control below.

<%@ Page Language="VB" AutoEventWireup="false"
CodeFile="Default.aspx.vb" Inherits="_Default" %>
<%@ Register Assembly="WebControlLibrary1"
Namespace="WebControlLibrary1" TagPrefix="wcl" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Test Page</title>
</head>
<body>
<form id="form1" runat="server">
<wcl:KeyedDropDownList id="ddlTest" runat="server">
<asp:ListItem Value="1">Calendar</asp:ListItem>
<asp:ListItem Value="2">Can</asp:ListItem>
<asp:ListItem Value="3">Candle</asp:ListItem>
<asp:ListItem Value="4">Canary</asp:ListItem>
<asp:ListItem Value="5">Card</asp:ListItem>
<asp:ListItem Value="6">Cat</asp:ListItem>
<asp:ListItem Value="7">Cow</asp:ListItem>
</wcl:KeyedDropDownList>
</form>
</body>
</html>
posted on May 31, 2006  #    by Mike Dugan  Comments [0]
 Tuesday, May 30, 2006

I encountered a troubling message while playing around with SQL Server 2005 and its new Integration Services. It read, “Failed to save package file "C:\Documents and Settings\Adam Anderson\Local Settings\Temp\tmp44F.tmp" with error 0x80029C4A "Error loading type library/DLL.".”

I first saw the error when I tried to create an Integration Services project in Visual Studio 2005, but the project was created anyway. I opened the project and ignored the error, hoping it was merely a glitch. However, after setting up a data source, I tried to add a package, and was blocked by the same error message. Now I knew I was in trouble. This was a brand-new installation, and it was annoying to see such an uninformative message, which is usually a sign that something has gone wrong at a fundamental level. Fortunately, my situation was not unique, and a search on Google quickly brought me to the correct solution.

It turns out that the MSXML 6.0 Parser was either incompletely installed or the installation was damaged.

To fix:

  1. Start Menu | Control Panel | Add or Remove Programs
  2. Locate MSXML 6.0 Parser in the list
  3. Click Change. The Setup dialog will appear.
  4. Click Next.
  5. There will be two options: Repair and Remove. Select Repair, then click Next.
  6. The Setup dialog will display a progress bar and then (hopefully) report success.
posted on May 30, 2006  #    by Adam Anderson  Comments [1]
 Monday, April 24, 2006

While browsing the web today, I came across a recommendation for Foxit Reader as an alternative to the more well-known Adobe Acrobat Reader. After downloading it and trying it out, I am happy to report that my first impressions of the product are very positive. Some of my biggest causes for discontent with Adobe Acrobat were the sluggish loading times and persistent nagging to upgrade, and both of these are a thing of the past with Foxit. Now when I double-click a PDF file, it opens in the blink of an eye! Farewell, Acrobat. Your slowness and nagging won't be missed.

posted on April 24, 2006  #    by Adam Anderson  Comments [0]