Archive

Archive for March, 2012

Logging lambda expressions

March 30, 2012 Leave a comment

When working with lambda expressions, there are scenarios where I need to log when a Func<bool> returns false. In the example below, just logging “condition was not met” doesn’t give me very much information.

public void SomeMethod(Func<Person, bool> condition)
{
	if (!condition(person))
	{
		Log.Info("Condition was not met.");
		return;
	}

	// Do something
}

If I called the method like so:

obj.SomeMethod(x => x.Name == "Malvin");

… I would like to be able to turn that lambda expression into a meaningful string.

Unfortunately, there doesn’t appear to be an easy way to turn a lambda expression into a readable string. Instead, I had to use expression trees.

public void SomeMethod(Expression<Func<Person, bool>> expression)
{
	if (!expression.Compile()(person))
	{
		Log.Info("Condition was not met: " + expression);
		return;
	}

	// Do something
}

Now if I call the method and the condition fails, I should see:

Condition was not met: x => (x.Name == "Malvin")

However, expression trees are much more expensive than lambda expressions. Running a non-scientific benchmark on my Core i7 @ 3.2 GHz yields some fairly obvious results.

void Main()
{
	Stopwatch sw = Stopwatch.StartNew();
	
	for (int i = 0; i < 100000; i++)
		UsingExpression(() => false);
	
	sw.Stop();
	
	Console.WriteLine ("Expression: " + sw.ElapsedMilliseconds);
	
	sw.Restart();
	
	for (int i = 0; i < 100000; i++)
		UsingLambda(() => false);
		
	sw.Stop();
	
	Console.WriteLine ("Lambda: " + sw.ElapsedMilliseconds);
}

public void UsingExpression(Expression<Func<bool>> expression)
{
	if (expression.Compile()())
		Console.WriteLine ("hello world");
}

public void UsingLambda(Func<bool> condition)
{
	if (condition())
		Console.WriteLine ("hello world");
}

Output:

Expression: 4154
Lambda: 0

This may be a problem for high volume systems, but I don’t think the extra overhead will be an issue for most cases.

Casting and converting to strings

March 13, 2012 1 comment

One thing that makes me nervous while looking through a code base is the liberal use of the ToString() method everywhere. There are a couple different ways to convert/cast to a string:

Explicit cast:

string str = (string)someObj;

ToString() method:

string str = someObj.ToString();

Convert.ToString() method:

string str = Convert.ToString(someObj);

as operator:

string str = someObj as string;

Explicit casts should be used at times when you are sure that someObj is a string. It also doubles as an assertion since an InvalidCastException will be thrown at runtime if the cast fails. The result will be null if attempting to cast a null object.

The ToString() method returns the string representation of an object. If someObj is null, a NullReferenceException will be thrown.

The Convert.ToString() method behaves differently depending on the type of object passed to the method. When an object is passed to the method, it calls the ToString() method on the object:

public static string ToString(Object value) 
{
	return ToString(value, null);
} 

public static string ToString(Object value, IFormatProvider provider) 
{ 
	IConvertible ic = value as IConvertible; 
	
	if (ic != null)
		return ic.ToString(provider); 
		
	IFormattable formattable = value as IFormattable;
	
	if (formattable != null)
		return formattable.ToString(null, provider);
		
	return value == null ? String.Empty : value.ToString(); 
}

When a string is passed to the Convert.ToString(), it simply passes through:

public static String ToString(String value) 
{
	Contract.Ensures(Contract.Result<string>() == value);
	return value; 
}

This is important to remember because if a null object is passed to the Convert.ToString() method, an empty string is returned. However, if a null string is passed to the method, a null is returned.

The as operator provides a way to cast an object without throwing an exception if the cast fails. If a cast fails, the result will be null.

Finding number of rows and disk space in SQL Server

March 6, 2012 1 comment

To see how many rows a table contains or how much disk space a table is using, we can use the system stored procedure sp_spacedused to quickly return information about a table or the database.

For a single table, we can pass the table name to the stored procedure:

We can execute the stored procedure without passing a table name to see how much disk space the entire database is using:

We can combine this system stored procedure with the undocumented stored procedure sp_msforeachtable to view the number of rows and disk space usage for all tables in the current database:

However, we have to keep in mind that the numbers being reported by sp_spaceused may not be immediately accurate after an index or table has been dropped, a table has been truncated, etc… since the information is not maintained in real time. The command dbcc updateusage may be execute to update the information for a single table or the entire database. Similarly, the sp_spaceused stored procedure may be executed with an additional parameter to update the information for a single table or the entire database:

-- Single table
sp_spaceused @objname = 'Person.Address', @updateusage = 'true'

-- Entire database
sp_spaceused @updateusage = ‘true’

Although we’ve executed the update commands above, the row counts may still be inaccurate. The commands above only updates the disk space usage information, but not the row count information stored in the table sysindexes. We may execute the command dbcc updateusage with the count_rows argument to update sysindexes:

-- Single table
dbcc updateusage ('AdventureWorks', 'Person.Address') with count_rows

-- Entire database
dbcc updateusage (0) with count_rows