Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Tuesday, August 31, 2010

A quick note on ADO.NET 2.0 and SQL performance in a normalized database

Back again after a while...

So I recently came across the problem, that an ADO.NET typed DataTable could perform pretty bad when used with the default generated CRUD commands. The situation is that if you create a typed DataTable for an SQL table in VS2008 by using an SQL SELECT, then the dataset designer will create the appropriate INSERT, UPDATE and DELETE tableadapter commands for you (if you ask for it). The main drawback of this approach is its main advantage: these generated commands will be general enough to handle columns with default values, or values generated by database-side triggers on-the-fly, etc. And at the same time UPDATE will be fairly inefficient when these tables reside in a normalized model, as it will identically update all unmodified columns in the database also, mainly those which are the foreign keys of the table. Updating unmodified columns might causes totally useless but really expensive index updates, and slow foreign key checks (even if you're using smart indexing). These costs run higher quickly if the depth of the tables grow, and can easily turn to be the main bottleneck of the overall system performance.

In such cases I suggest to override default generated UPDATE command to only update those columns which are actually subject to change.

Wednesday, August 13, 2008

log4net: hostname in logfile's name

I recently came across the problem that while using the excellent log4net tool with fileappender I needed to programatically include the machine name in the logfile's name (the application's config is on a shared disk area, so hard-wiring the nodename was not an option). Thanks to the log4net team, since version 1.2.9 this can be achieved via the PatternString and the ConversionPattern classes. Let's see a working c# example.

This is what you should put into your application's config (Web.config in my case) to the <log4net> section:

<appender name="SomeLogFileAppender" type="log4net.Appender.FileAppender">
<file type="log4net.Util.PatternString" >
<converter>
<name value="hostname" />
<type
value="MyNamespace.MySubNamespace.HostnamePatternConverter,MyNamespace" />
</converter>
<conversionPattern
value="debuglog-%hostname{LocalApplicationData}.txt" />
</file>
<appendToFile value="true" />
<rollingStyle value="Date" />
<datePattern value="yyyyMMdd" />
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level - %message%newline" />
</layout>
</appender>

And then the code snippet which implements HostnamePatternConverter:


using log4net;
using System;


namespace MyNamespace.MySubNamespace {

...

public class HostnamePatternConverter : log4net.Util.PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
writer.Write(Environment.MachineName);
}
}

...

}