Wednesday, October 27, 2004

Code Generation with Codesmith
I did a little bit survey about the Microsoft reporting service tools; Here is the detail.

1. This tools need a SQL server instance to store some application Meta data for internal use. But it can use oracle as data source for reporting. It is basically free if we have an sql server license.

2. This tools includes a simple query builder and a report layout designer, we could use report layout designer to visually adjust the report layout and some format stuffs such as the column width, Font. The report layout designer will generate a RDL (report definition language) script based on the outcome of designer GUI, the report query is embedded into RDL script too, and we could modify the RDL script manually or Programmatically.

3. This tools includes a report server that do the query&format based on the RDL script we made by report layout designer, the server will retrieve the data and format the report according the output type we specified, output type could be web page, excel or PDF.

4. This tools use RDL script as the interface between the report design GUI and report build&format engine, this way would improve and shorten the process of the design and creation of a brand new report.
But the RDL also bring some drawback, the first thing is that this tools only provide some basic RDL syntax, (RDL is a kind of extensible script, the different development tools vendor could add their own predefined syntax into it). So the reporting build&format engine can only recognize the syntax they have, if we have some complex reports that need some special format effect, this tools cann't accomplish it.
There are a simple workaround for this issue, we could use this tools to do the basic layout and simple formating, and develop another module to do the complex formatting based on the excel file built by this tools.

Introducing the Microsoft reporting service in MSDN TV

Reporting Services Programming

Monday, October 18, 2004

I figure out a way about getting the distinct store count from the summary table, and here is the detail.
We have a summary table like it


period_key	item_key	store_key

20030102 1 1
20030102 1 2
20030102 1 5
20030102 1 7
20030102 1 9
..
20030302 1 2
20030302 1 5
20030302 1 6
20030302 1 8



We normally use the following Query to run against the summary table and get the
distinct store count




Select count(distinct store_key) from [summary table]
Where period_key between ? and ?
And item_key = ?



If the summary table has lots of rows, this query would be running long time.

We only need to know the position of each store in store lookup table when we are calculating the distinct store count, so we could come out the following structure



Bit Position 1 2 3 4 5 6 7
Store key 1 2 5 6 7 8 9

{1,2,5,7,9} 1 1 1 0 1 0 1
{2,5,6,8} 0 1 1 1 0 1 0



The store lookup table doesn’t have too many records, so we could just use a
column which type is varchar2 to store the resulting bit string for store key.



period_key item_key store_key_raw
20030102 1 1110101
20030302 1 0111010



Once we need to get the distinct count of store, we could just do BIT_OR operation
on this column, and get the distinct store count by counting the amount of 1 bit inside the final bit string for store key. there are an existing Oracle function UTL_RAW.BIT_OR that could do BIT_OR operation to two strings, and it is quite fast, there are some code snippets.




PROCEDURE test_raw_or IS
lvc_cursor ref_cursor;
lvn_counter BINARY_INTEGER;
lvs_a VARCHAR2(4000);
raw_a RAW(4000);
raw_b RAW(4000);
raw_c RAW(4000);
BEGIN
-- get the bit string for store key
OPEN lvc_cursor FOR
SELECT store_key_raw
FROM store_bitmap;

-- use loop to do the bit_or for all of rows
lvn_counter := 0;
lvs_a := '';
LOOP
EXIT WHEN lvc_cursor%NOTFOUND;
lvn_counter := lvn_counter + 1;

FETCH lvc_cursor
INTO lvs_a;
raw_a := utl_raw.cast_to_raw(lvs_a);
IF lvn_counter > 1 THEN
raw_c := utl_raw.bit_or(raw_a, raw_b);
raw_b := raw_c;
ELSE
raw_b := raw_a;
END IF;

END LOOP;
CLOSE lvc_cursor;

-- get the final bit string for store key
INSERT INTO calc_store_bitmap
VALUES
(utl_raw.cast_to_varchar2(raw_c));

-- get the distinct store count by counting the amount of 1 bit inside the
final bit string for store key
....

End;



There are another problem raised that UTL_RAW.BIT_OR could only do the BIT_OR on
two strings, it couldn’t do the BIT_OR on a column in a table. It is not convenient for us to write SQL,

Fortunately oracle 9i has a great feature named as User defined aggregate functions, you could do any aggregate operation with it, just like the regular oracle aggregate functions such as sum or count. First all, we need to create a new oracle type that includes a set of oracle pre-defined member function. such as ODCIAggregateInitialize, ODCIAggregateiterate. Then we could write the code to override these functions. The following is code snippets.




-- define a temp variable to store the middle value
total raw(4000),
--override the function that is doing the Iteration
member function ODCIAggregateIterate(self IN OUT str_agg_type,
value IN raw )
return number
is
begin
self.total := utl_raw.bit_or(self.total, value);
return ODCIConst.Success;
end;
--override the function that returns the final result
member function ODCIAggregateTerminate(self IN str_agg_type,
returnValue OUT raw,
flags IN number)
return number
is
begin
returnValue := self.total;
return ODCIConst.Success;
end;




And I created two functions to get the distinct store count, the first one is a User
defined aggregate function raw_bit_or_agg(input varchar2) that is used to do the BIT_OR on a column in the table, this function is just like other aggregate function. Another is count_bit_in_str that could get the bit count from a string, so the Query that getting count will be like this,




SELECT count_bit_in_str(raw_bit_or_agg(p.store_bitmap))
FROM [summary table] p
WHERE p.period_key BETWEEN ? AND ?
And p. item_key = ?
ORDER BY p.period_key




I wrote a unit test app to compare the difference, the method using BIT_OR is

500 times faster than the one using count(distinct store_key).

Saturday, October 16, 2004

I did some survey on MS .net rich client automated upgrading solution recently, here is the detail

1 MS Updater Application Block
It is a open source framework that supports .net 1.1 framework and VS.2003, it includes a simple start app and a configuration file in the client side, the configuration file stores the address of file server that might be FTP, web, or shared file folder. There is a ServerManifest.xml that is located in the root folder of file server; this file includes all of files that need to be upgraded and their latest version number.
When the start app is launched, it will check the info inside the ServerManifest.xml, and compare with current application files in the client side, if the version # is not matched, and there are new version available, the start app will pop up a window to ask if you‘d like to upgrade the current application files, and the start app will do all of file downloading and replacing automatically if you client YES.

MS Updater Application Block

2 DotNet No-Touch Deployment (NTD)
DotNet No-Touch Deployment is a zero deployment application solution (smart client).
it supports .net 1.1 framework and VS.2003 too, it includes two methods.

the first method is that hosting the winform application into a web server, so user can lanuch it with a URL in IE or commend line. the app will be downloaded from web and setting into local internet cache, it doesn't require download every time unless there are new version in server side. and it could use the web service to connect with database, so the client side doesn't need install the oracle client. it requires a little changes in start section of winform app to make it work.

another method is embeding the .net winform coltrol into a web page, and put them to web server. it is similar to some original methods such as activex, but MS made some improvement, such as the size of control is much smaller than before.

DotNet No-Touch Deployment (NTD)



3 ClickOnce
ClickOnce is part of .net 2.0 framework, and supports VS.2005; it will be available in 2005.
It provides a home page for every application, the user could access the application by a URL inside this home page, you could choice to install the app in client machine or run the app in client cache, and it also support automated upgrading if you install the application in the client machine.

ClickOnce

4 Avalon
Avalon will be with the windows longhorn that was scheduled to be released in 2006, and it will support the Windows XP too. its start app is a XAML file that could be located in the client PC or server side such as a web server, this XAML file is similar to web page, but it doesn’t require IE, Avalon also support automated upgrading.

There are also some third party solutions available such as updated component suite; they are similar to MS Updater Application Block.
Walkthrough – Generating RDL Using the .NET Framework