LINQ to XML -How to use XPass for elements selection

I am just starting to work with LINQ to XML and tried to find child document similar to the following:
 xml.Element(“client/child”);
But it throw exception
System.Xml.XmlException: The ‘/’ character, hexadecimal value 0x2F, cannot be included in a name.
The reason is that LINQ to XML doesn’t directly support XPAth
Fortunately there are extensions, that allow to use XPath for XElement search/selection.

using System.Xml.XPath;

and then

var clients = xml.XPathSelectElements ( “client/child” );

Consider, if required ,an XPathSelectElements overload  with namespace management.

Note, that XPath extensions are actually backward compatibility feature, and Microsoft recommends to use native XElement methods, such as Descendants ,Elements,Element etc.  See Comparison of XPath and LINQ to XML
 However K. Scott Allen  prefers to mix LINQ and XPath  to have concise code.

See also Concepts LINQ to XML for XPath Users

Useful tip:where clause and “Possible System.NullReferenceException”

Misleading error message when NullReferenceException thrown within Comparer

We’ve got an error messgae from custom comparer:
IComparer (or the IComparable methods it relies upon) did not
return zero when Array.Sort called x. CompareTo(x).
 
After investigation it was found, that the error was caused by NullReferenceException,
 thrown within Comparer.
I’ve suggested to Microsoft , that the actual NullReferenceException error message should be shown instead of this misleading one.
See also similar feedback
 

EnsureDirectoryExists helper function

Below is a simple EnsureDirectoryExists helper function:

public static void EnsureDirectoryExists(string targetPath)
        {
            string dir = Path.GetDirectoryName(targetPath);
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
        }

Use HashSet instead of “seen” Hashtable.

In our code (originally created in .Net 1.1)  there are a few examples of “seen” Hashtable pattern
 
Hashtable seen = new Hashtable();
for (int i = 0; i < nCount; i++)
{
    if (seen[key] == null)
    {
        //Do the changes
        seen.Add(key, key);
    }
}
 
It's better to use type-safe HashSet:
 
HashSet<string> seen = new HashSet<string>();
for (int i = 0; i < nCount; i++)
{
    if (!seen.Contains(key))
    {
        //Do the changes
        seen.Add(key);
    }
}

Don’t Repeat Yourself(DRY principle) when modifying existing function

If there is an existing  non-trivial function and you need to change it , do NOT copy and paste it , but modify to satisfy new requirements.
You may be need to split a big function into small ones and call them in different order or with different parameters.
Often you need just to add extra parameter to the function and have if-else branches depending on a new parameter.
In some cases new change is actually a fix of the problem, that applicable to all usages of the function.
Remember that “Copy and Paste” is NOT a good way of code re-use.
 
I also strongly recommend to read Exploring Smelly Code article to avoid other anti-patterns.
 

Typed DataTable’s base class in VS008

I have a typed Dataset, generated by VS Designer. Resently I’ve added a new column to one of the tables, and suddently in different DLLs where the dataset was used, I’ve started to get

Error 22 The type ‘System.Data.TypedTableBase`1<T0>’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’.

 

Apparently VS 2008 changed the base class for Typed DataTables 

3.5 : public partial class SubusersDataTable : global::System.Data.TypedTableBase<SubusersRow> {

2.0: public partial class SubusersDataTable : global::System.Data.DataTable, global::System.Collections.IEnumerable {

 and you need to change all dependant assemblies to

target 3.5 framework (if not done yet) and

add a reference to assembly ‘System.Data.DataSetExtensions, Version=3.5.0.0 

 

More details about the change from http://blogs.msdn.com/vbteam/archive/2008/05/14/how-linq-to-dataset-works-in-vb-jonathan-aneja.aspx

Note that for strongly-typed Datasets you don’t need to call AsEnumerable, as they inherit from TypedTableBase(Of T) which implements IEnumerable.  This is a new type in VS2008; in VS2005 the Dataset Designer would generate code that inherited from DataTable and then explicitly implemented IEnumerable itself.

 

Safe Save DateTime to SQL Database.

When I tried to save DateTime data to SQL database, I’ve got 
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM.
I’ve had to create a function
object SafeSqlDateTime(DateTime dtValue)
{
object theValue = dtValue;
if (dtValue <(DateTime) SqlDateTime.MinValue) // January 1, 1753.
{
   theValue =
null;

}
return theValue;

For opposite SqlDateTime to DateTime Conversion see
http://msdn.microsoft.com/en-us/library/aa326475(VS.71).aspx