Wednesday, April 25, 2007

Set up the Database Trace Listener in Enterprise Library.

I am getting very interested in Microsoft Enterprise Library lately for a couple of reasons:
  • It addresses a couple of common issues you will normally face, like logging, caching, and you really don't want to do those plumbing code if possible.
  • It gives you a nice configuration tool ( you can open this tool within visual studio for the Enterprise Library 3) .
  • It gives you all the source code, so you can see what's under the hood.
I am playing with the Logging application block in last two days, the best way to learn those tools is always to check the QuickStart source code. I found the quick start doesn't provide an example to show you how you can log the error into the database, which I believe is the most used cases in the system.

I did a brief research, and you actually have to reference another dll (Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll) in order to be able to log into the database.

Basically, you have to do the following steps :
1. The "Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll" has to be referenced.
2. The scripts under "C:EntLib3SrcApp BlocksSrcLoggingTraceListenersDatabaseScripts" has to be run against the database to create the necessary tables and objects.
3. The "Database Trace Listener" has to be added to the "Trace Listeners". For the trace listener, you have to specify the Formatter, otherwise, you will get an error.
4. Put the "Trace Listener" under the Category you want to log.

Here is a screenshot of the configuration file..

Saturday, April 21, 2007

Try to avoid sql generated names if you want to use change scripts to do the database upgrade.

Sometime, if you don't explicitly name an object when you create an object in sql server, the sql server will create a default name for you. It is not too bad if you have some sophisticated tool to migrate your database. But if you want to run your change scripts manually , it's best that you name every object you created, not relying on the system generated name.

One way to create an object in the sql server is normally dropping it firstly, that's where I got hit when relying on the system generated name.

I have an sql script like this:

IF dbo.ColumnAlreadyExists('BusinessCategory','IsActive')=1
ALTER TABLE BusinessCategory DROP COLUMN IsActive

ALTER TABLE BusinessCategory ADD IsActive Bit DEFAULT 1

It's fine when I ran it the first time, it generated the new column for me, but when I ran it again, it complains there is a default constraint object on the IsActive column which needed to be dropped firstly. The issue is the system generated a long name for my default constraint. The name is long, hard to remember, and could be changing, so it makes the changes scripts hard to write.

So, the better way is to use a named object instead like this:

ALTER TABLE BusinessCategory ADD IsActive Bit
ALTER TABLE BusinessCategory ADD CONSTRAINT BusinessCategory_Default DEFAULT 1 FOR IsActive

That way, you can always drop the named constraint if you want to drop it like this:

IF dbo.ColumnAlreadyExists('BusinessCategory','IsActive')=1
ALTER TABLE BusinessCategory DROP CONSTRAINT BusinessCategory_Default
ALTER TABLE BusinessCategory DROP COLUMN IsActive

Wednesday, April 11, 2007

The debugger may cheat you on cache.

Cache is pretty tricky to work with. On one side, you have to use it to improve the performance of your application, On the other side, cache is very tricky to work with and needs careful consideration when putting it into your application.

I recently works on a state government project which uses a lot of cache in the application. Simply put, it uses a static class to cache a lot of lookup tables. One simple example is like this:

public static class Cache
public LookupTable TestTypes
HttpRunTime.Cache.Insert("TestTypes", CreateTestTypes(), SqlDependency);
return HttpRunTime.Cache["TestTypes"];

This code looks perfect, but it throws out mysterious exceptions a lot of times.

There are two issues here:

1> Don't run HttpRunTime.Cache["TestTypes"] twice, even HttpRunTime.Cache["TestTypes"]==null returns false, when you actually gets the value from HttpRunTime.Cache["TestTypes"], it could be reevaluated and return null.
2> Even you insert HttpRunTime.Cache.Insert("TestTypes", CreateTestTypes(), SqlDependency) here, the insertion may fail, say, there is an out of memory situation, you cannot gurantee HttpRunTime.Cache["TestTypes"] is not null.

LookupTable lookupTable=Cache.TestTypes; If you assert the value returned by the lookupTable is not equal to null, like this: Debug.Assert(lookupTable!=null), you will see a strange phenomena when the debugger stops at this point: the lookupTable is null, but the right side of the expression is NOT null.

This is because the Cache.TestTypes is reevaluated by the debugger, and its value is not the same value when the code executes, which was NULL. I know it's a little bit confusing. When you put the Cache.TestTypes in the watcher window, the debugger actually checks if HttpRunTime.Cache["TestTypes"] is null again. And if it is, it will insert the value into the cache again.

A more robust way is handle the cache like this:

public static class Cache
public LookupTable TestTypes
TestTypes testTypes= HttpRunTime.Cache["TestTypes"];
HttpRunTime.Cache.Insert("TestTypes", testTypes, SqlDependency);
return testTypes;

1. K. Scott Allen Wierd Caching
2. Peter Johnson HttpRuntime.Cache vs. HttpContext.Current.Cache
3. 蝈蝈俊.net HttpRuntime.Cache vs. HttpContext.Current.Cache

Sunday, April 08, 2007

As you know, you have to go to war with the Army you have, not the Army you want,"

This is what Rumsfeld said. I am sure this infamous saying also played a rule for his step down as Secretary of Defense. But I guess it also applies to a lot of developers like us. As a developer, you normally don't have the option to choose the best tools you have because you are the money maker, but NOT the money decision maker.

In the company worked before, we use visual studio professional to develop some performance sensitive application (GIS). The application involves a lot of graphics rendering, geometry processing, some real hard-core algorithm. We encounter some performance issue, and really would like some professional tools to profile it. But again, we cannot make the decision, because the visual studio team edition costs much more than the professional edition.

Now, I am working on Team Edition for software developer on my new job, but my current job uses so much database functionality, and I really hope I can have Team Suite, which contains the database piece of the Team edition. But again, I cannot make that decision.

Sometimes, as a developer, you just have to work the best with what you have. If you cannot make a decision or persuade the management to make a decision to offer sophisticated tools for you, just try to find some open source, or free tools.

Sometimes, you may have to go back to use some old fashion command way to finish your stuff.

I really hope I, as a developer, have more right in the company to decide what tools I want to use.

Saturday, April 07, 2007

Another google impressive product-google pin yin.

For people who don't type chinese , it may be a little bit hard to understand. A lot of chinese people had hard time to input chinese like me. It's not because there is no good input tools, I know, there are a few very good input tools available. But to use those tools efficiently, you have to be very good at "pin yin". A lot of people like me spoke a dialect which is far away from standard mandarin, which is most input methods are based upon. The following is a fuzzy logic that google uses to make sure those non-standard speaker could have a decent input speed.

For myself, I am terrible at mixing some of them, like those pairs (an-ang, en=eng).

Another good feature is that you can have google store your selection patter on the server, so, it can automatically retrieve your selection next time. A good example, when I type my name, I put jianwei, and it will put my name as the first choice, because it remembered my choice of the last time.

I am waiting for another impressive product from google...