Moving to Office

Re-orgs happen frequently at Microsoft and I am about to experience one.

I just got two Ship-Its for the product I have been working on for almost 2 years, Microsoft Equipt, which will be discontinued after April 30th. We just finished the last feature of the product: requesting refund via the home page. The feature is now RTW. All in all, I have participated the design and implementation of all two versions of the product, starting from just an idea, all the way to its sunset.

I am going to Join Office and work on a new product.

Weird Error of Log Parser

Log Parser is a great Microsoft tool for processing text-based data. Its scriptable COM components can be easily consumed by .NET applications.

Recently I ran into an interesting error when using the COM components with C#. The data input for the parser is a TSV ((tab-separated values) formatted text log file. Here is code:

LogQueryClassClass logQuery = new LogQueryClassClass();
COMTSVInputContextClassClass inputContext = new COMTSVInputContextClassClass();
inputContext.iCheckpoint = “MyCheckpoint.lpc”;
ILogRecordset recordSet = logQuery.Execute(“SELECT * FROM test.log”, inputContext);

I got all NULL values in the result records or the following exception:

Unhandled Exception: System.Runtime.InteropServices.COMException (0x80094004): Error parsing query: Header for file “test.log” contains an empty field name declaration [Unknown Error]

The weird thing is if I commented out the line which assigns iCheckpoint for incremental parsing, the code would work. Eventually I found out that I needed to specify the CodePage of the inputContext since the text input was encoded in Unicode. So the solution is to add the following line:

inputContext.CodePage = -1; // -1 is Unicode, default (0) is the system codepage

SQLClient Support for the New Date and Time Types in SQL Server 2008

Prior to SQL Server 2008, SQL developers were restricted to using two types to work with date and time values: datetime and smalldatetime. While they are sufficient in most user scenarios, there are some limitations:

1)      Both types include both the date value and time value. There is no way to store only the date or time part. This causes wasted storage and difficulties in computation and indexing.

2)      The range supported of the datetime type does not align with the range of .NET CLR DateTime type.

3)      The datetime precision of .333 seconds is not sufficient for some applications.

4)      The types are not time-zone aware.

To address these limitations, SQL Service 2008 introduced four new date/time data types: date, time, datetime2, datetimeoffset. The first two types are date-only and time-only respectfully. time type supports user-defined fractional second precision. datetime2 combines date and time into a single data type. datetimeoffset has all the features of datetime2 with an additional time zone offset. The range of datetime2 and datetimeoffset are fully aligned with the .net CLR types DateTime and DateTimeOffset (introduced in .NET Framework 3.5).

In .NET Framework 3.5, SQLClient has been extended to support the four new types.

Type Version System

To enable the feature, the first step is to explicitly specify the Type Version System to SQL Server 2008 or Latest in the connection string. Otherwise, the client would be treated like a SQL Server 2005 client. Here is the code snippet:

using (SqlConnection conn = new SqlConnection(“Server=localhost;Integrated Security=SSPI;Type System Version=SQL Server 2008”))

{

conn.Open();

//…

}

Scale for time, datetime2, and datetimeoffset

For time, datetime2, and datetimeoffset, users are allowed to define the fractional second precision. It might sound confusing, the correct term for it is scale. With scale = x, the increment would be 1/10X seconds. So you should use the Scale property in SqlParameter to specify the fractional second precision and you look for the Scale column in the schema table returned by SqlDataReader.GetSchemaTable().

CLR Type Mapping and Inference

date, datetime2 are mapped to DateTime. time is mapped to TimeSpan. datetimeoffset is mapped to DateTimeOffset. datetime2 and datetimeoffset have the same range as their CLR counterparts.

For SqlParameter, if you use AddWithValue method, DateTime would always be inferred as datetime. To explicit specify the value as datetime2, you need to set the SqlDbType to SqlDbType.DateTime2.

Some New SqlClient APIs Related to New Date/Time Types

New SqlDbType enumerations:

SqlDbType.Date

SqlDbType.Time

SqlDbType.DateTime2

SqlDbType.DateTimeOffset

New SqlDataReader methods:

SqlDataReader.GetDateTimeOffset()

SqlDataReader.GetTimeSpan()

Lessons Learned from A Scam

This post contains some hard lessons I recently learned through a craigslist transaction. Hopefully it could help you to become more cautious if you decide to sell something through craigslist or other similar online sites.

A while ago I won a competition at the company and the prize was an Xbox 360 with a 20G hard drive. However, I’m not a big fan of video games and I decided to sell the brand-new sealed package. Since I had some previous good experience with selling things through craigslist, I posted an ad in craigslist again this time. In Amazon the retail price for this type of Xbox 360 is $400 and I asked for $300. It was obviously a good deal and a few guys replied to the ad immediately after it was posted. I decided to make a deal with the guy who replied first. He asked to meet in the same afternoon. We made the transaction and everything seemed to be running smoothly. However, later in the evening, the guy sent me an email claiming the hard drive didn’t work. I was a little bit surprised because when I handed it to him, the box was still sealed.

I replied the next morning to talk with him and ask for the error he got. I told him it’s hard to find out exactly when the hard drive went wrong but I’d like to help to solve the problem by contacting Microsoft Support. However, he became nasty and claimed I was running a scam. In his email, he talked to me in a very threatening way. He said he recorded my license plate number (and proved it by including the correct number in the e-mail) and he would take care of this the hard way if I didn’t refund him. This was totally unexpected as I was responding to his emails all the way along. To avoid confrontation with a potentially dangerous guy, I refund him fully in the same evening. However, after coming back home, I found the controller was missing in the box. Since then, he has never answered my calls or replied to my emails.

I’m very suspicious he actually conned me. I feel it’s possible the original Xbox has no problem at all and he just replaced it with a bad hard drive and stole the controller with it. The email he sent to me was just to scare me and make me refund him his money.

Several lessons learned:

1. Always be very cautious when you use any public sites to make some deals. I’m not complaining about any specific website but most of them are open to everyone. It would be safer if the targeted audience could be limited. As far as I know, in Windows Live Expo, you could specify that the ads you’ve posted can only be viewed by people in your community, such as among all Microsoft employees.

2. Protect your identity as much as possible when dealing with strangers from the Internet. Only provide necessary information. Of course, if someone acts like this guy who purposely recorded your license plate number during the meeting, there’s not a lot you could do about it.

3. Don’t lose your composure. I could have found out the controller was missing up front if I had more composure. Of course the result might still be the same: the guy could have claimed he would bring it another time and then disappeared.

Meanwhile, doing business online can be enjoyable and I wish everybody good luck.

Performance Tips with SqlClient

Here’s a list of things to know if you’d like achieve the best performance/scalability with SqlClient:

  1. Use SqlBulkCopy to send large sets of data to the server
  2. Set DbDataAdapter.UpdateBatchSize to send batches to the server
  3. Use strongly typed getters instead of GetValue/GetSqlValue
  4. Turn on CommandBehavior.SequentialAccess and call GetChars/GetBytes when working with BLOBs
  5. Use parameterized queries (Avoids conversion to and from nchar type)
  6. Wrap multi-step operations in a transaction
  7. Use connection pooling

You might also be interested in check out this article: Improving ADO.NET Performance.

Seattle Works Day 2007

1,000+ participants at 30+ project sites added up to nearly 4,000 hours of service in a single day. Seattle Works Day is a fun and easy way to green up Seattle.

Microsoft also broke Seattle Works Day records. We had three projects this year with over 300 participants – our largest group ever. Microsoft has sponsored each individual on the Microsoft team so it’s free for us.

I signed up for the Washington Middle School project. We went weeding, edging, and laying bark mulch at the school. Our help is important as the Seattle School District has limited resources and they have committed to reducing the use of pesticides to make this area safer for all.

The good: the Green theme. It’s great to see we’re making an effort to keep our urban green spaces beautiful and available for safe outdoor recreational activities.

The bad: nothing really bad, although I felt the music was a little too loud at the after-party. It could have been easier for me to meet more people and talk with them.

The dirty: it was raining throughout the time we were doing the project. I’m actually a special person who enjoys raining. With the rain, getting dirty part is even more fun. 🙂

I joined Seattle Works Day 2006 and I’m looking forward to Seattle Works Day 2008.

New Adventure

After working in SQL for more than 19 months, I have decided to pursue a new opportunity in Office Live. On June 1, I’ll begin my Office Live adventure.

10 Reinvigorating Facts About Microsoft’s Profits

I’d like to share an interesting article on Microsoft’s profits published a while ago:

10 Reinvigorating Facts About Microsoft’s Profits

Microsoft last week announced quarterly revenue of $14.4 billion and net income of $4.93 billion. In other words, Microsoft’s daily net income is about $55 million. That’s $55 million in pure profit every 24 hours. Do some quick math and you’ll learn it takes Microsoft only about…

  • 10 hours or so (yes, hours!) to exceed Red Hat’s (NYSE: RHTNews) quarterly net income of $20.5 million.
  • four days to exceed Research In Motion’s (NasdaqGS: RIMM) quarterly net income of $187.9 million.
  • four days to exceed Starbucks’ (NasdaqGS: SBUX) quarterly net income of $205 million.
  • one week to exceed Nike’s (NYSE: NKENews) quarterly net income of $350.8 million.
  • two weeks to exceed McDonalds’ (NYSE: MCDNews) quarterly net income of $762 million.
  • two weeks to exceed Apple’s (NasdaqGS: AAPL) quarterly net income of $770 million.
  • 18 days to exceed Google’s (NasdaqGS: GOOG) quarterly net income of $1 billion.
  • 23 days to exceed Coca-Cola’s (NYSE: KONews) quarterly net income of $1.26 billion.
  • five weeks to exceed IBM’s (NYSE: IBMNews) quarterly net income of $1.85 billion.
  • 10 weeks to exceed Wal-Mart’s (NYSE: WMTNews) quarterly net income of $3.9 billion.
  • While I feel impressed and proud, I realize it’s challenging for Microsoft to keep or even exceed the current achievement. To grow a multi-billion business, in my opinion, is way harder than to grow a multi-million business. The dynamics of the IT software industry are changing in a very fast pace. Customers expect constantly innovations and there’re new competitors coming up every day. Nevertheless, I strongly believe Microsoft will continue to excel with her smart employees, firm leadership, and healthy corporate culture.

Progressive Development

My mentor James at Microsoft recently started a blog with the name “Progressive Development”. It talks about best and worst practices of software engineering in the format of entertaining conversations between two figures Motley and Maven.

I knew James through his class at Microsoft and he is a fantastic teacher with excellent engineering knowledge and passion on software quality. His blog entries on engineering practices are definitely worth reading.

Progressive Development: Zany Adventures in Software Engineering with Maven and Motley

More on MSDTC

Last time I wrote a post on MSDTC under Vista. Here I’d like to talk a general MSDTC issue, which is not Vista-specific.

Internally MSDTC uses NetBIOS names and passes them to RPC to talk to remote machines. This requires both server and client to be able to resolve each other’s machine name.

Sometimes things can get messed up with DHCP or DNS caching. An easy workaround is to add entries with machine names and IP addresses in your hosts file. You probably need to do this on both the server and the client if neither could resolve the name.