Synchronizing SQL Server and SQL Azure

September 22, 2010 § Leave a comment

Synchronizing SQL Server and SQL Azure


(Source ::: databasejournal.com)


SQL Azure Data Sync provides data synchronization between the cloud and
local SQL Server databases. Learn how SQL Azure Data Sync allows you to
keep the most concurrent information in the cloud while allowing mobile
users, businesses, and enterprise data sources all to have access to
this data.

Introduction

In an effort to bring a flexible cloud-computing experience Microsoft has
introduced the Microsoft Azure platform. One of the many offerings is the cloud-based
relational database service built on SQL Server technologies called Microsoft
SQL Azure Database
. To help keep managed data movement between the
cloud based SQL Azure Database and your local SQL Server databases, Microsoft
has provided a tool called SQL Azure Data Sync. Let’s look closer at this powerful
tool.

SQL Azure Data Sync allows one to keep the most concurrent information in
the cloud (SQL Azure) and allows mobile users, businesses, and enterprise data
sources all to have access to this data, which is in the cloud, facilitating
office machines as well as mobile desktop and handhelds to work together.

SQL Azure Data Sync Features

SQL Azure Data Sync allows:

  • Data synchronization between SQL Azure databases. Imagine Ebay.com
    sharing customer profile information to Google to help target customers
    with relevant advertisements and both their databases would be in the
    cloud.
  • Data synchronization between SQL Azure database and on-premise SQL
    Server data. Imagine a Point-of-sale device which a salesperson will
    use to update available inventory in his office (cold call results in
    sales, he updates the on-premise) and also update the inventory when he
    makes client visits

It also provides Microsoft Visual Studio templates, which allow developers
to bring the SQL Azure Database to SQL Compact Databases.

Getting Started

To get started, you need to do the following:

Using the SQL Azure Data Sync Tool

Once you have signed up for the offer mentioned above and activated your account, visit https://sql.azure.com/projectviewer.aspx and setup your database. To allow for the SQL Azure Data Sync tool
to work, you will need to allow filters for the external IP address of
the machine from which you are running the Data Sync tool.

Here is how the screen looks.

setting up your database

Once you have setup the SQL database, copy the database name and administrator name for use in the Data Sync tool.

Start the SQL Azure Data Sync tool.

SQL Azure Data Sync tool

Click Next.

Enter the Azure SQL database credentials you created above. Once you
enter the credentials, test the connection by clicking on “Test
Connection”. If you get an error saying connection failed despite
providing the right credentials, double check that the external IP is
allowed through the firewall settings.

check that the external IP is allowed through the firewall settings

Click Next. On this screen, enter the name and credentials for the local database you want to use for syncing with the Microsoft Azure database.

enter the name and credentials for the local database

Click Next. On the next page, select the tables that need to be
synchronized. Also, select the database that will prevail in case of
conflicts. Then click Next.

select the tables which need to be synchronized

On the next screen, choose the table ordering.

choose the table ordering

On the summary page, name your synchronization job and click Process.

name your synchronization job and click Process

Once you click Process, it will create a Job with the name specified
which will be visible under SQL Server Management studio under “SQL
Server Agent -> Jobs”. Whenever you want to synchronize your
database, you now only need to run this job.

Using the SQL Azure Offline Plug in for Microsoft Visual Studio

Data Synchronization is also easier programmatically. If you have
installed the tools mentioned above and you have Microsoft Visual Studio
2008 Professional, you will get a new item template called SqlAzureDataSyncClient. When it is added to a project, SqlAzureDataSyncClient automatically does the underlying plumbing and makes the necessary classes to facilitate data synchronization.

The steps are similar to the Data Sync tool. The only difference here is that when you add a new item “SQLAzureDataSyncClient“,
a wizard pops up and asks a bunch of questions that captures the
information, which is then used to create the classes and project
references.

Conclusion

We saw how SQL Azure Data Sync tools work and what they are used for.
I hope that this information will be useful when you are working to
synchronize your data between Azure Database and your local SQL Server
database. Happy Syncing!

Advertisements

Concatenating row values in Transact-SQL

September 18, 2010 § Leave a comment

Concatenating row values in Transact-SQL

Introduction

Many a time, SQL programmers are faced with a requirement to generate report-like resultsets right off of a Transact SQL
query. In most cases, the requirement arises from the fact that there are no sufficient tools or in-house expertise to develop
tools that can extract the data as a resultset and massage the data in the desired display format. Quite often folks are
confused about the potential of breaking relational fundamentals say like First Normal Form or the scalar nature of typed
values. (Talking about 1NF violations in a language like SQL which lacks sufficient domain support, allows NULLs and supports
duplicates is somewhat ironic to begin with, but that is a topic which requires detailed explanations.)

Concatenating column values or expressions from multiple rows are usually best done in a client side application language,
since the string manipulation capabilities of Transact SQL and SQL based DBMSs are somewhat limited. However, you can do these
using different approaches in Transact SQL, but avoiding such methods for long term solutions is your best bet.

A core issue

Even though SQL in general deviates considerably from the relational
model, its reliance on certain core aspects of relational
foundations makes SQL functional and powerful. One such core aspect is
the set based nature of SQL expressions (well, multi-sets
to be exact, but for the given context let us ignore the issue of
duplication). The primary idea is that tables are unordered
and hence the resultsets of any query that does not have an explicit
ORDER BY clause is unordered as well. In other words, the rows
in a resultset of a query do not have a prescribed position, unless it
is explicitly specified in the query expression.

On the other hand, a concatenated list is an ordered structure. Each
element in the list has a specific position. In fact,
concatenation itself is an order-utilizing operation in the sense that
values can be prefixed or post fixed to an existing list. So
approaches that are loosely called “concatenating row values”,
“aggregate concatenation” etc. would have to make sure that some kind
of an order, either explicit or implicit, should be specified prior to
concatenating the row values. If such an ordering criteria
is not provided, the concatenated string would be arbitrary in nature.

Considerations

Generally, requests for row value concatenations often comes in two
basic flavors, when the number of rows is known and small (typically
less than 10) and when the number of rows is unknown and potentially
large. It may be better to look at each of them separately.

In some cases, all the programmer wants is just the list of values from a
set of rows. There is no grouping or logical partitioning
of values like the list of email addresses separated by a semicolon or
some such. In such situations, the approaches can be the same
except the join conditions may vary. Minor variations of the examples
list on this page illustrate such solutions as well.

For the purpose of this article the Products table from Northwind
database is used to illustrate column value concatenations with a
grouping column. Northwind is a sample database in SQL Server 2000
default installations. You can download a copy from from the
Microsoft Downloads
Consider the resultset produced by the following query:

    SELECT CategoryId, ProductName 
      FROM Northwind..Products ;
  
    CategoryId  ProductName                              
    ----------- ---------------------------------------- 
    1           Chai
    1           Chang
    ...
    2           Aniseed Syrup
    2           Chef Anton's Cajun Seasoning
    ...
    ...
    8           Spegesild
    
    (77 row(s) affected)

The goal is to return a resultset with two columns one with the Category
Identifier and the other with a concatenated list of all
the Product Names separated by a delimiting character, say a comma for
instance.

    CategoryId  Product List
    ----------- -----------------------------------------------------------------------------
    1           Chai, Chang, Chartreuse verte, Côte de Blaye, ...
    2           Aniseed Syrup, Chef Anton's Cajun Seasoning, ...
    3           Chocolade, Gumbär Gummibärchen, Maxilaku, ...
    4           Camembert Pierrot, Flotemysost, Geitost, Gorgonzola Telino, ...
    5           Filo Mix, Gnocchi di nonna Alice, Gustaf's Knäckebröd, ...
    6           Alice Mutton, Mishi Kobe Niku, Pâté chinois, ...
    7           Longlife Tofu, Manjimup Dried Apples, Rössle Sauerkraut, ...
    8           Boston Crab Meat, Carnarvon Tigers, Escargots de Bourgogne, ...
    
    (8 row(s) affected)
 

Concatenating values when the number of items is small and known upfront

When the number of rows are small and almost known upfront, it is easier
to generate the code. One common approach with a small set
of finite rows it the pivoting method. Here is an example where only
first four alphabetically sorted product names per categoryid is
retrieved:

    SELECT CategoryId,
           MAX( CASE seq WHEN 1 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 2 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 3 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 4 THEN ProductName ELSE '' END )
      FROM ( SELECT p1.CategoryId, p1.ProductName,
                    ( SELECT COUNT(*) 
                        FROM Northwind.dbo.Products p2
                       WHERE p2.CategoryId = p1.CategoryId
                         AND p2.ProductName <= p1.ProductName )
               FROM Northwind.dbo.Products p1 ) D ( CategoryId, ProductName, seq )
     GROUP BY CategoryId ;

The idea above is to create a expression inside the correlated subquery
that produces a rank (seq) based on the product names and
then use it in the outer query. Using common table expressions and the
ROW_NUMBER() function, you can re-write this as:

; WITH CTE ( CategoryId, ProductName, seq )
    AS ( SELECT p1.CategoryId, p1.ProductName,
                ROW_NUMBER() OVER ( PARTITION BY CategoryId ORDER BY ProductName )
           FROM Northwind.dbo.Products p1 )
    SELECT CategoryId,
           MAX( CASE seq WHEN 1 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 2 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 3 THEN ProductName ELSE '' END ) + ', ' +
           MAX( CASE seq WHEN 4 THEN ProductName ELSE '' END )
      FROM CTE 
     GROUP BY CategoryId ;

Note that ROW_NUMBER() is a newly introduced feature in SQL 2005. If you
are using any previous versions, you will have to use the
subquery approach (You can also use a self-join, to write it a bit
differently). Using the recently introduced PIVOT operator, you
can write the above as following :

    SELECT CategoryId, 
           "1" + ', ' + "2" + ', ' + "3" + ', ' + "4" AS Product_List
      FROM ( SELECT CategoryId, ProductName, 
                    ROW_NUMBER() OVER (PARTITION BY CategoryId ORDER BY ProductName)
               FROM Northwind.dbo.Products ) P ( CategoryId, ProductName, seq )
     PIVOT ( MAX( ProductName ) FOR seq IN ( "1", "2", "3", "4" ) ) AS P_ ;

Not only the syntax appears a bit confusing, it does not appear to offer
anything functionally beyond the CASE approach above. However,
in rare situations, it could come in handy.

Concatenating values when the number of items is not known

When the number of items that are to be concatenated is not known
upfront, the code can become a bit more demanding. The new features
in SQL 2005 make some of the approaches a bit easy. For instance, the
recursive common table expressions (CTEs) and the FOR XML PATH(”)
syntax makes the server do the hard work behind the concatenation
leaving the programmer to deal with the presentation issues. The
examples below make this point obvious.

Recursive CTE methods

The idea behind this method is from a newsgroup posting by Vadim
Tropashko similar to the ideas behind generating a materialized path
for hierarchies.

    WITH CTE ( CategoryId, product_list, product_name, length ) 
          AS ( SELECT CategoryId, CAST( '' AS VARCHAR(8000) ), CAST( '' AS VARCHAR(8000) ), 0
                 FROM Northwind..Products
                GROUP BY CategoryId
                UNION ALL
               SELECT p.CategoryId, CAST( product_list + 
                      CASE WHEN length = 0 THEN '' ELSE ', ' END + ProductName AS VARCHAR(8000) ), 
                      CAST( ProductName AS VARCHAR(8000)), length + 1
                 FROM CTE c
                INNER JOIN Northwind..Products p
                   ON c.CategoryId = p.CategoryId
                WHERE p.ProductName > c.product_name )
    SELECT CategoryId, product_list 
      FROM ( SELECT CategoryId, product_list, 
                    RANK() OVER ( PARTITION BY CategoryId ORDER BY length DESC )
               FROM CTE ) D ( CategoryId, product_list, rank )
     WHERE rank = 1 ;

The CASE in the recursive part of the CTE is used to eliminate the
initial comma and you can use RIGHT or the SUBSTRING functions
to substitute it. Also, this may not be the best performing option,
however certain additional tuning could be done to make them
suitable for medium sized datasets.

Another approach using recursive common table expressions was sent in by
Anub Philip, an Engineer from Sathyam Computers that uses
separate common table expressions for the anchor and recursive parts.

    WITH Ranked ( CategoryId, rnk, ProductName )  
             AS ( SELECT CategoryId,
                         ROW_NUMBER() OVER( PARTITION BY CategoryId ORDER BY CategoryId ),
                         CAST( ProductName AS VARCHAR(8000) ) 
                    FROM Northwind..Products),
   AnchorRanked ( CategoryId, rnk, ProductName )  
             AS ( SELECT CategoryId, rnk, ProductName 
                    FROM Ranked
                   WHERE rnk = 1 ),
    RecurRanked ( CategoryId, rnk, ProductName ) 
             AS ( SELECT CategoryId, rnk, ProductName 
                    FROM AnchorRanked
                   UNION ALL 
                  SELECT Ranked.CategoryId, Ranked.rnk,
                         RecurRanked.ProductName + ', ' + Ranked.ProductName
                    FROM Ranked
                   INNER JOIN RecurRanked 
                      ON Ranked.CategoryId = RecurRanked.CategoryId 
                     AND Ranked.rnk = RecurRanked.rnk + 1 )
    SELECT CategoryId, MAX( ProductName ) 
      FROM RecurRanked
     GROUP BY CategoryId;

On an initial glance, this query may seem a bit expensive in comparison,
however the reader is encouraged check the execution plans and
make any additional tweaks as needed.

The blackbox XML methods

An example for string concatenation using FOR XML clause with PATH mode
is detailed below. It was initially posted by Eugene Kogan
later became common in public newsgroups.

    SELECT p1.CategoryId,
          ( SELECT ProductName + ',' 
              FROM Northwind.dbo.Products p2
             WHERE p2.CategoryId = p1.CategoryId
             ORDER BY ProductName
               FOR XML PATH('') ) AS Products
      FROM Northwind.dbo.Products p1
     GROUP BY CategoryId ;

Again, the similar approach originally found in the beta newsgroups, using CROSS APPLY operator.

    SELECT DISTINCT CategoryId, ProductNames
      FROM Products p1
     CROSS APPLY ( SELECT ProductName + ',' 
                     FROM Products p2
                    WHERE p2.CategoryId = p1.CategoryId 
                    ORDER BY ProductName 
                      FOR XML PATH('') )  D ( ProductNames )

You may notice a comma at the end of the concatenated string, which you
can remove using a STUFF, SUBSTRING or LEFT function. While the
above methods are deemed reliable by many at the time of writing, there
is no guarantee that it will stay that way given the internal
workings and evaluation rules of FOR XML PATH() expression in correlated
subqueries are not well documented.

Using Common Language Runtime

Though this article is about approaches using Transact SQL, this section
is included due to the popularity of CLR aggregates in SQL 2005. Not
only it
empowers the CLR programmer with new options for database development,
in some cases, they work at least as well as native Transact
SQL approaches.

If you are familiar with .NET languages, SQL 2005 offers a convenient
way to create user defined aggregate functions using C#, VB.NET or
similar languages that is supported by the Common Language Runtime
(CLR). Here is an example of a string concatenate aggregate function
written using C#.

    using System;
    using System.Collections.Generic;
    using System.Data.SqlTypes;
    using System.IO;
    using Microsoft.SqlServer.Server;

    [Serializable]
    [SqlUserDefinedAggregate(Format.UserDefined,  MaxByteSize=8000)]
    public struct strconcat : IBinarySerialize{
        private List values;

        public void Init()    {
            this.values = new List();
        }

        public void Accumulate(SqlString value)    {
            this.values.Add(value.Value);
        }

        public void Merge(strconcat value)    {
            this.values.AddRange(value.values.ToArray());
        }

        public SqlString Terminate()    {
            return new SqlString(string.Join(", ", this.values.ToArray()));
        }

        public void Read(BinaryReader r)    {
            int itemCount = r.ReadInt32();
            this.values = new List(itemCount);
            for (int i = 0; i <= itemCount - 1; i++)    {
                this.values.Add(r.ReadString());
            }
        }

        public void Write(BinaryWriter w)    {
            w.Write(this.values.Count);
            foreach (string s in this.values)      {
                w.Write(s);
            }
        }
    }

Once you build and deploy this assembly on the server, you should be able to execute your concatenation query as:

    SELECT CategoryId, 
           dbo.strconcat(ProductName) 
      FROM Products 
     GROUP BY CategoryId ; 

If you are a total newbie on CLR languages, and would like to learn more
about developing database solutions using CLR languages,
consider starting at Introduction to Common Language Runtime (CLR)
Integration

Scalar UDF with recursion

Recursive functions in t-SQL have a drawback that the maximum nesting
level is 32. So this approach is applicable only for smaller
datasets, especially when the number of items within a group, that needs
to be concatenated, is less than 32.

    CREATE FUNCTION udf_recursive ( @cid INT, @i INT ) 
    RETURNS VARCHAR(8000) AS BEGIN 
        DECLARE @r VARCHAR(8000), @l VARCHAR(8000) 
        SELECT @i = @i - 1,  @r = ProductName + ', ' 
          FROM Products p1 
         WHERE CategoryId = @cid 
           AND @i = ( SELECT COUNT(*) FROM Products p2 
                       WHERE p2.CategoryId = p1.CategoryId 
                         AND p2.ProductName <= p1.ProductName ) ; 
        IF @i > 0 BEGIN 
              EXEC @l = dbo.udf_recursive @cid, @i ;
              SET @r =  @l + @r ;
    END 
    RETURN @r ;
    END 

This function can be invoked as follows:

    SELECT CategoryId, 
           dbo.udf_recursive( CategoryId, COUNT(ProductName) ) 
      FROM Products 
     GROUP BY CategoryId ; 

Table valued UDF with a WHILE loop

This approach is based on the idea by Linda Wierzbecki where a table
variable with three columns is used within a table valued UDF.
The first column represents the group, second represents the currently
processing value within a group and the third represents the
concatenated list of values.

    CREATE FUNCTION udf_tbl_Concat() RETURNS @t TABLE(
            CategoryId INT, 
            Product VARCHAR(40), 
            list VARCHAR(8000) ) 
    BEGIN 
     INSERT @t (CategoryId, Product, list) 
     SELECT CategoryId, MIN(ProductName),  MIN(ProductName) 
       FROM Products 
      GROUP BY CategoryId 
    WHILE ( SELECT COUNT(Product) FROM @t ) > 0 BEGIN 
        UPDATE t 
           SET list = list + COALESCE(
                         ( SELECT ', ' + MIN( ProductName ) 
                             FROM Products 
                            WHERE Products.CategoryId = t.CategoryId 
                              AND Products.ProductName > t.Product), ''), 
               Product = ( SELECT MIN(ProductName) 
                             FROM Products 
                            WHERE Products.CategoryId = t.CategoryId 
                              AND Products.ProductName > t.Product ) 
          FROM @t t END 
    RETURN 
    END 

The usage of the above function can be like:

    SELECT CategoryId, list AS Products
      FROM udf_tbl_Concat() ; 

Dynamic SQL

This approach is a variation of the kludge often known using the nickname as dynamic cross tabulation.

This approach is a variation of the kludge often known using the
nickname as dynamic cross tabulation. There is enough literature out
there which demonstrates the drawbacks and implications of using Dynamic
SQL. A popular one, at least from Transact SQL programmer’s
perspective, is Erland’s Curse and Blessings of Dynamic SQL.
The Dynamic SQL
approaches can be developed based on creating a Transact SQL query
string based on the number of groups and then use a series of CASE
expressions or ROW_NUMBER() function to pivot the data for
concatenation.

    DECLARE @r VARCHAR(MAX), @n INT, @i INT 
    SELECT @i = 1,
           @r = 'SELECT CategoryId, ' + CHAR(13), 
           @n = (SELECT TOP 1 COUNT( ProductName ) 
                   FROM Products 
                  GROUP BY CategoryId 
                  ORDER BY COUNT( ProductName ) DESC ) ;	
    WHILE @i <= @n BEGIN 
	    SET @r = @r + 
	    CASE WHEN @i = 1  
	         THEN 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + ' 
                                 THEN ProductName 
				                 ELSE SPACE(0) END ) + ' + CHAR(13) 
      	     WHEN @i = @n 
             THEN 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + ' 
                                 THEN '', '' + ProductName 
                                 ELSE SPACE(0) END ) ' + CHAR(13) 
             ELSE 'MAX( CASE Seq WHEN ' + CAST( @i AS VARCHAR ) + ' 
                                 THEN '', '' + ProductName 
                                 ELSE SPACE(0) END ) + ' + CHAR(13)  
	    END ;
 	    SET @i = @i + 1 ;
    END 
    SET @r = @r + ' 
    FROM ( SELECT CategoryId, ProductName, 
                  ROW_NUMBER() OVER ( PARTITION BY CategoryId ORDER BY ProductName )
             FROM Products p ) D ( CategoryId, ProductName, Seq ) 
           GROUP BY CategoryId;' 
    EXEC( @r ) ;

The Cursor approach

The drawbacks of rampant usage of cursors are well-known among the
Transact SQL community. Given the fact that they are generally
resource intensive, procedural and inefficient, one should strive to
avoid cursors or loop based solutions in general Transact SQL
programming.

    DECLARE @tbl TABLE (id INT PRIMARY KEY, list VARCHAR(8000)) 
    SET NOCOUNT ON 
    DECLARE @c INT, @p VARCHAR(8000), @cNext INT, @pNext VARCHAR(40) 
    DECLARE c CURSOR FOR 
        SELECT CategoryId, ProductName 
          FROM Products 
         ORDER BY CategoryId, ProductName ;
        OPEN c ;
        FETCH NEXT FROM c INTO @cNext, @pNext ;
        SET @c = @cNext ;
        WHILE @@FETCH_STATUS = 0 BEGIN 
             IF @cNext > @c BEGIN 
                  INSERT @tbl SELECT @c, @p ;
                  SELECT @p = @PNext, @c = @cNext ;
             END ELSE 
                  SET @p = COALESCE(@p + ',', SPACE(0)) + @pNext ;
             FETCH NEXT FROM c INTO @cNext, @pNext 
        END 
        INSERT @tbl SELECT @c, @p ;
        CLOSE c ;
    DEALLOCATE c ;
    SELECT * FROM @tbl ;

Non-reliable approaches

This section details a couple of notorious methods often publicized by
some in public forums. The problem with these methods is that
they rely on the physical implementation model; changes in indexes,
statistics etc or even a change of a simple expression in the
SELECT list or ORDER BY clause can change the output. Also these are
undocumented, unsupported and unreliable to the point where one
can consistently demonstrate failures. Therefore these methods are not
at all recommended for production mode systems.

Scalar UDF with t-SQL update extension

The usage of an expression that involves a column, a variable and an
expression in the SET clause in an UPDATE statement rarely appear
intuitive. However, in general, the optimizer often seems to process
these values in the order of materialization, either in the internal
work tables or any other storage structures.

    CREATE FUNCTION udf_update_concat (@CategoryId INT) 
        RETURNS VARCHAR(MAX) AS 
    BEGIN 
    DECLARE @t TABLE(p VARCHAR(40));
    DECLARE @r VARCHAR(MAX) ;
        SET @r = SPACE(0) ;
        INSERT @t ( p ) SELECT ProductName FROM Products 
                         WHERE CategoryId = @CategoryId ;
        IF @@ROWCOUNT > 0 
            UPDATE @t 
               SET @r = @r + p + ',' ;
        RETURN(@r) 
    END 

Here is how to use this function:

    SELECT CategoryId, dbo.udf_update_concat(CategoryId) 
      FROM Products 
     GROUP BY CategoryId ; 

Again, it is important to consider that lack of physical independence
that is being exploited here before using or recommending this as
a usable and meaningful solution.

Scalar UDF with variable concatenation in SELECT

This is an approach purely dependent on the physical implementation and
internal access paths. Before using this approach, make sure to
refer to the relevant knowledgebase article.

    CREATE FUNCTION dbo.udf_select_concat ( @c INT )
    RETURNS VARCHAR(MAX) AS BEGIN
    DECLARE @p VARCHAR(MAX) ;
           SET @p = '' ;
        SELECT @p = @p + ProductName + ','
          FROM Products
         WHERE CategoryId = @c ;
    RETURN @p
    END

And, as for its usage:

    SELECT CategoryId, dbo.udf_select_concat( CategoryId )
      FROM Products
     GROUP BY CategoryId ;

Conclusion

Regardless of how it is used, "aggregate concatenation" of row values in
Transact SQL, especially when there is a grouping, is not
a simple routine. Various programming considerations are to be carefully
considered to choose one method over another depending on
the situations. The most logical choice would be the availability of a
built-in operator with optional configurable parameters that
can do the concatenation of the values depending on the type. Till then,
reporting requirements and external data export routines
will have to rely on such Transact SQL programming hacks.

A Brief Introduction to the Java and .NET Patent Issues (Source ::: infoq.com)

September 14, 2010 § Leave a comment

A Brief Introduction to the Java and .NET Patent Issues

Let’s start with Java. With Java you have two options for licensing.
First, you can use (possibly with your own modifications) the code from
OpenJDK. Second, you can make a new implementation of Java, based on the
Java specification.

There is no explicit patent license covering OpenJDK. OpenJDK is covered by GPLv2 and
it is generally believed that when one licenses code under GPLv2 that
license includes an implicit patent license. In 2004 Dan Ravicher,
senior counsel for the Free Software Foundation, warned about the weak patent guarantees for BSD and GPL and recommended attaching patent grants.

This means the scope of the implicit patent license is unclear. On
the one hand if all you do is use OpenJDK unmodified you should be
completely covered. On the other hand if you made such extensive changes
that it is no longer recognizable as Java and now infringes some Oracle
non-Java patent, you would probably not be covered by the implicit
license. Where exactly you cross the line from covered to uncovered is
very fuzzy and unclear.

If you go with the option of making your own implementation, then
there is an explicit patent license. That license covers you if you
implement the complete specification, and if you do not make certain
prohibited changes (adding fields and methods to the standard classes,
putting new things in the standard namespaces, stuff like that), and if
your implementation passes the "Technology Compatibility Kit".

The big problem with this is the TCK requirement. Sun could (and did)
withhold access to the TCK from people who were doing things it did not
like with Java. No TCK, no patent license for your implementation. In
2007 Geir Magnusson of Apache issued an open letter complaining about
the Harmony project was unable to "acquire an acceptable license for the Java SE 5 technology compatibility kit."

Neither of the above options would work for Google. They couldn’t go
with the OpenJDK option for a couple of reasons. First, it is GPL. The
handset makers and the carriers want to add proprietary features to
distinguish themselves from their competitors, and Google felt Android
would have a hard time getting accepted if it was under a license that
did not allow this. Second, Java SE (which is what OpenJDK implements)
is not really suitable for devices like phones. If Google morphed the
code to be more like Java ME, they would be in that fuzzy area where no
one would be sure whether or not the implicit patent license covers
them.

Implementing their own Java following the Java SE specification, and
then extending it (carefully avoiding making any changes to the parts
that the patent license prohibits changing) might have worked–but they
would still have the TCK problem. That path too would be a very rocky
road, since Sun wanted Google to simply license Java ME.

Hence, Google went with using Java syntax and semantics, but not using the Java VM. No patent protection.

Now let’s compare to .NET, and whether or not Google using Mono would
have been safer. Microsoft’s patent license for independent .NET
implementations is the Microsoft Community Promise.
Like Sun’s patent license, it does require that you implement all
mandatory parts of the specification. Unlike Sun’s, there is no
particular test that you are required to pass, and limitations on
enhancing things. Implement the mandatory things in the spec–you are
golden. (If you do enhance things, those enhancements won’t be covered
by the promise, of course, so some care is still required).

So right off the bat the patent situation is better–you don’t have
to get Microsoft’s approval of your implementation in order to get your
patent license. This fits in much better with what Google was trying to
do.

Mono implements the mandatory parts of the spec, plus enhancements.
Some of those enhancements are implementations of Microsoft .NET
frameworks that are not part of the spec, such as WinForms. Those parts of Mono could have patent problems, so if Google had used Mono those would best be avoided.

Google might have still had to modify Mono to make it more suitable
for small low-power devices like phones. That could take them outside of
the ECMA/ISO spec, and into patent risks. However, there is a thing
called the .NET Micro Framework from Microsoft, which kind of
corresponds to Java ME. Note the license for .NET Micro Framework: Apache2.
That license comes with an explicit patent grant. If Google had made
Android based on a mix of Mono and code from .NET Micro Framework, they
could likely have made it so all parts are covered against Microsoft
patents–the Community Promise covering all the ECMA/ISO standard parts
and the patent grant with the Apache2 licensing covering the
enhancements for mobile.

What it really comes down to is that Microsoft followed the normal
rules for opening up a technology. They submitted both the C# language
and the .NET infrastructure to an independent standards body. They
provided a patent license that covers implementation of those standards
with no restrictions other than the common and normal restriction that
you have to implement the required portions of the standard.

Sun did not follow the normal rules. They refused to submit Java to
an independent standards body. They put strings on their patent license
for the standard that effectively required you to get their approval of
your implementation before you could get a license. Later, they did
release OpenJDK under GPL, which was an improvement, but they did not
accompany it with an explicit patent license, so no one knows just what
you can do with OpenJDK (beyond using it unmodified) without running the
risk of a patent suit from Sun/Oracle.

C# Delegates: Step by Step

September 12, 2010 § Leave a comment

C# Delegates – Step by Step

At first glance, delegates are difficult to absorb
because the usage of a delegate runs against conventional thinking on a
how a method should be called. During a conventional method call, you
create an object that contains the methods you want to call, invoke the
method, passing the required parameters. Everything happens in one pop,
including defining what object and method to call and invoking the call.
The method call through delegation takes a different approach. It
splits up the definition of the method call and the actual invocation of
the method into two parts. Delegates are the .NET version of addresses
to methods. They are type-safe classes that define the return types and
types of parameters. The delegate class not only not only contains a
reference to a method, but holds references to multiple methods. Even
though delegates have been around since .NET 2.0, they play an important
role in .NET 4 today. Lambda Expressions are directly related to
delegates. When the parameter is a delegate type, you can use a Lambda
expression to implement a method that’s referenced from the delegate.
Delegates exist for situations in which you pass methods around to other
methods. To see what this means, consider this code :

# Sample Snippet #

using System;
public class Test
 {
  public delegate int CalculationHandler(int x, int y);
  static void Main(string[]  args)
   {
     Math math = new Math();
    //create a new instance of the delegate class

     CalculationHandler sumHandler = new CalculationHandler(math.Sum);
    //invoke the delegate
      int result = sumHandler(8,9);
     Console.WriteLine("Result is: " + result);
     }
   }

 public class Math
  {
    public int Sum(int x, int y)
     {
       return x + y;
     }
  }

Result is: 17

The information encapsulated inside a delegate about a
method can be categorized into two groups: method signature and method
target. Method signature includes information about the number and type
of the method parameters as well as the return type. Method target
includes the name of the method and the object in which the method
resides. When we create a delegate object that encapsulates a method
call, we must provide these two sets of information.

The first thing we need to do to use delegation in
our program is to define a delegate class by specifying the signature of
the method the delegate class is capable of handling. In our example,
we defined a delegate class called CalculationHandler that is capable of
handling a method with two integer parameters and an integer return
value. If the method doesn’t have any return value, then we must use
“void” instead. After we have defined CalculationHandler, it becomes the
inner class of the existing class (in our case, the Test class).

After we have defined a delegate class, the next step
is to create an instance of the class and bind it to the specific
target. It is important to note that, first, the delegate class has only
one constructor, which takes the method target as its only parameter.
This binds the delegate object to a physical target. Second, the method
target specified in the constructor must match the method signature
defined in the delegate class. That is, we have to make sure that the
Sum method matches with the definition of CalculationHandler, which says
that the target method must take two integer parameters and have an
integer return value.

In this next example we instantiate a delegate of
type GetAString, and then initialize it so it refers to the ToString()
method of the integer variable x. Delegates in C# always syntactically
take one-parameter constructor, the parameter being the method to which
the delegate will refer. This method must match the signature with which
you originally defined the delegate. So in this case, we would get a
compilation error if we tried to initialize the variable
firstStringMethod with any method that did not take any parameters and
return a string. Notice that, because int.ToString() is an instance
method (as opposed to a static one), we need to specify the instance ( x
) as well as the name of the method to initialize the delegate
properly. The next line actually uses the delegate to display the
string. In any code, supplying the name of a delegate instance, followed
by brackets containing any parameters, has exactly the same effect as
calling the method wrapped by the delegate.

# Sample Snippet #

using System;
public class Program
 {
   public delegate string GetAString();
   public static void Main()
        {
            int x = 40;
            GetAString  firstStringMethod = x.ToString;
            Console.WriteLine("String is {0}", firstStringMethod());
            Currency balance = new Currency(34, 50);
             // firstStringMethod references an instance method
            firstStringMethod = balance.ToString;
            Console.WriteLine("String is {0}", firstStringMethod());
             // firstStringMethod references a static method
            firstStringMethod = new GetAString(Currency.GetCurrencyUnit);
            Console.WriteLine("String is {0}", firstStringMethod());

        }
    }

You see that there is a Currency class that creates an object:

# Sample Snippet #

using System;
public class Currency {
       public uint Dollars;
        public ushort Cents;
     public Currency(uint dollars, ushort cents)
        {
            this.Dollars = dollars;
            this.Cents = cents;
        }
    public override string ToString()
        {
            return string.Format("${0}.{1,-2:00}", Dollars, Cents);
        }
     public static string GetCurrencyUnit()
        {
            return "Dollar";
        }
    public static explicit operator Currency(float value)
        {
            checked
            {
                uint dollars = (uint)value;
                ushort cents = (ushort)((value - dollars) * 100);
                return new Currency(dollars, cents);
            }
        }
       public static implicit operator float(Currency value)
        {
            return value.Dollars + (value.Cents / 100.0f);
        }

        public static implicit operator Currency(uint value)
        {
            return new Currency(value, 0);
        }

        public static implicit operator uint(Currency value)
        {
            return value.Dollars;
        }
    }

csc.exe /t:library Currency.cs

csc.exe /r:Currency.dll Program.cs

OUTPUT:

String is 40
String is $34.50
String is Dollar

This example defines a MathOperations class that has a
couple of static methods to perform two operations on doubles. Then we
use delegates to call up these methods. The math class looks like this:

# Sample Snippet #

using System;
public class MathOperations
    {
        public static double MultiplyByTwo(double value)
        {
            return value * 2;
        }

        public static double Square(double value)
        {
            return value * value;
        }
    }

We call up these methods like this:

# Sample Snippet #

using System;
 delegate double DoubleOp(double x);

    class Application
    {
        static void Main()
        {
            DoubleOp[] operations =
            {
               MathOperations.MultiplyByTwo,
               MathOperations.Square
            };

            for (int i = 0; i < operations.Length; i++)
            {
                Console.WriteLine("Using operations[{0}]:", i);
                ProcessAndDisplayNumber(operations[i], 2.0);
                ProcessAndDisplayNumber(operations[i], 7.94);
                ProcessAndDisplayNumber(operations[i], 1.414);
                Console.WriteLine();
            }
        }

        static void ProcessAndDisplayNumber(DoubleOp action, double value)
        {
            double result = action(value);
            Console.WriteLine(
               "Value is {0}, result of operation is {1}", value, result);
        }
    }

Output:


Using operations[0]:
Value is 2, result of operation is 4
Value is 7.94, result of operation is 15.88
Value is 1.414, result of operation is 2.828

Using operations[1]:
Value is 2, result of operation is 4
Value is 7.94, result of operation is 63.0436
Value is 1.414, result of operation is 1.999396

In this code, we instantiate an array of DoubleOp
delegates (remember that after we have defined a delegate class, you can
basically instantiate instances just as we can with normal classes, so
putting some into an array is no problem). Each element of the array
gets initialized to refer to a different operation implemented by the
MathOperations class. Then, we loop through the array, applying each
operation to three different values. This illustrates one way of using
delegates — that you can group methods together into an array using
them, so that you can call several methods in a loop. The key lines in
this code are the ones in which you actually pass each delegate to the
ProcessAndDisplayNumber() method, for example:

# Sample Snippet #

ProcessAndDisplayNumber(operations[i], 2.0);

Here is an example that should clarify the meaning of
delegates. Notice how there are two categories of information for each
instance. As we have seen, this indirection between two objects
promotes “decoupling”. Putting a delegate, or method object between a
client and a server enables us to define certain actions without
invoking them. This could be advantageous when running multiple
applications to achieve a task. We would want each application to have
little knowledge of the other; therefore, if one application changes in
behavior, say the one providing a service, then the application
consuming the service will not alter its behavior. The consumer of the
service will not change its operating procedures if the service provider
suddenly changes its operating procedures. The example below, however,
is meant to stick with the general principals of delegates:

# Sample Snippet #

using System;
class Program
{
    /// Delegate declaration.
    delegate string UppercaseDelegate(string input);
      /// Delegate implementation 1.
    static string UppercaseFirst(string input)
    {
        char[] buffer = input.ToCharArray();
        buffer[0] = char.ToUpper(buffer[0]);
        return new string(buffer);
    }

    /// 
    /// Delegate implementation 2.
    /// 
    static string UppercaseLast(string input)
    {
        char[] buffer = input.ToCharArray();
        buffer[buffer.Length - 1] = char.ToUpper(buffer[buffer.Length - 1]);
        return new string(buffer);
    }

  
    /// Delegate implementation 3.
      static string UppercaseAll(string input)
    {
        return input.ToUpper();
    }

    /// 
    /// Receives delegate type.
    /// 
    static void WriteOutput(string input, UppercaseDelegate del)
    {
        Console.WriteLine("Your string before: {0}", input);
        Console.WriteLine("Your string after: {0}", del(input));
    }

    static void Main()
    {
        // Wrap the methods inside delegate instances and pass to the method.
        WriteOutput("gems", new UppercaseDelegate(UppercaseFirst));
        WriteOutput("gems", new UppercaseDelegate(UppercaseLast));
        WriteOutput("gems", new UppercaseDelegate(UppercaseAll));
    }
}

Yields

OUTPUT:

Your string before: gems
Your string after: Gems
Your string before: gems
Your string after: gemS
Your string before: gems
Your string after: GEMS

Review

To put delegates to use, you need to define one or
more handler methods, assign the handler when instantiating a delegate,
and perform an invocation on the delegate instance. Here is an
appropriate example:

# Sample Snippet #

using System;

// 1. Define delegate.
public delegate double UnitConversion(double from);

class QuickDelegateDemo
{
    // 2. Define handler method.
    public static double FeetToInches(double feet)
    {
        return feet * 12;
    }

    static void Main()
    {
        // 3. Create delegate instance.
        UnitConversion doConversion = new UnitConversion(FeetToInches);

        Console.WriteLine("Feet to Inches Converter");
        Console.WriteLine("------------------------\n");
        
        Console.Write("Please enter feet:  ");
        double feet = Double.Parse(Console.ReadLine());

        // 4. Use delegate just like a method.
        double inches = doConversion(feet);

        Console.WriteLine("\n{0} Feet = {1} Inches.\n", feet, inches);
        Console.ReadLine();
    }
}

OUTPUT:

Feet to Inches Converter
------------------------

Please enter feet:  12

12 Feet = 144 Inches.

When we use a delegate to encapsulate method calls,
our mindset must shift from the conventional view of method calls to an
object-oriented view. Asynchronous programming produces powerful
applications for delegates. Similar to waiting on a long, drawn out
shopping line and being, idle, perhpas an analogy would be performing a
task while waiting for the person in front of you.

Application Architecture: An N-Tier Approach

September 11, 2010 § Leave a comment

Introduction

Developers must realize there is more to programming than simple code. This two-part series addresses the important issue of application architecture using an N-tier approach. The first part is a brief introduction to the theoretical aspects, including the understanding of certain basic concepts. The second part shows how to create a flexible and reusable application for distribution to any number of client interfaces. Technologies used consist of .NET Beta 2 (including C#, .NET Web Services, symmetric encryption), Visual Basic 6, the Microsoft SOAP Toolkit V2 SP2, and basic interoperability [ability to communicate with each other] between Web Services in .NET and the Microsoft SOAP Toolkit. None of these discussions (unless otherwise indicated) specify anything to do with the physical location of each layer. They often are on separate physical machines, but can be isolated to a single machine.

For starters, this article uses the terms "tier" and "layer" synonymously. In the term "N-tier," "N" implies any number, like 2-tier, or 4-tier, basically any number of distinct tiers used in your architecture.

"Tier" can be defined as "one of two or more rows, levels, or ranks arranged one above another" (see http://www.m-w.com/cgi-bin/dictionary?Tier). So from this, we get an adapted definition of the understanding of what N-tier means and how it relates to our application architecture: "Any number of levels arranged above another, each serving distinct and separate tasks." To gain a better understanding of what is meant, let’s take a look at a typical N-tier model (see Figure 1.1).


Figure 1.1 A Typical N-Tier Model

The Data Tier

Since this has been deemed the Age of Information, and since all information needs to be stored, the Data Tier described above is usually an essential part. Developing a system without a data tier is possible, but I think for most applications the data tier should exist. So what is this layer? Basically, it is your Database Management System (DBMS) — SQL Server, Access, Oracle, MySql, plain text (or binary) files, whatever you like. This tier can be as complex and comprehensive as high-end products such as SQL Server and Oracle, which do include the things like query optimization, indexing, etc., all the way down to the simplistic plain text files (and the engine to read and search these files). Some more well-known formats of structured, plain text files include CSV, XML, etc.. Notice how this layer is only intended to deal with the storage and retrieval of information. It doesn’t care about how you plan on manipulating or delivering this data. This also should include your stored procedures. Do not place business logic in here, no matter how tempting.

The Presentation Logic Tier

Let’s jump to the Presentation Logic Layer in Figure 1.1. You probably are familiar with this layer; it consists of our standard ASP documents, Windows forms, etc. This is the layer that provides an interface for the end user into your application. That is, it works with the results/output of the Business Tier to handle the transformation into something usable and readable by the end user. It has come to my attention that most applications have been developed for the Web with this layer talking directly to the Data Access Layer and not even implementing the Business Tier. Sometimes the Business Layer is not kept separated from the other two layers. Some applications are not consistent with the separation of these layers, and it’s important that they are kept separate. A lot of developers will simply throw some SQL in their ASP (using ADO), connect to their database, get the recordset, and loop in their ASP to output the result. This is usually a very bad idea. I will discuss why later.

The Proxy Tier and the Distributed Logic

There’s also that little, obscure Proxy Tier. "Proxy" by definition is "a person [object] authorized to act for another" (see http://www.m-w.com/cgi-bin/dictionary?Proxy). This "object," in our context, is referring to any sort of code that is performing the actions for something else (the client). The key part of this definition is "act for another." The Proxy Layer is "acting" on behalf of the Distributed Logic layer (or end-user’s requests) to provide access to the next tier, the Business Tier. Why would anyone ever need this? This facilitates our need for distributed computing. Basically it comes down to you choosing some standard method of communication between these two entities. That is, "how can the client talk to the remote server?"

This is where we find the need for the Simple Object Access Protocol (SOAP). SOAP is a very simple method for doing this. Without too many details, SOAP could be considered a standard (protocol) for accessing remote objects. It provides a way in which to have two machines "talking" or "communicating" with each other. (Common Object Request Broker Architecture [CORBA], Remote Method Invocation [RMI], Distributed Component Object Model [DCOM], SOAP, etc., all basically serve the same function.)

The Client Interface

In this section of Figure 1.1 we notice that the end-user presentation (Windows forms, etc.) is connected directly to the Business Tier. A good example of this would be your applications over the Local Area Network (LAN). This is your typical, nondistributed, client-server application. Also notice that it extends over and on top of the Distributed Logic layer. This is intended to demonstrate how you could use SOAP (or some other type of distributed-computing messaging protocol) on the client to communicate with the server and have those requests be transformed into something readable and usable for the end user.

The Business Tier

This is basically where the brains of your application reside; it contains things like the business rules, data manipulation, etc. For example, if you’re creating a search engine and you want to rate/weight each matching item based on some custom criteria (say a quality rating and number of times a keyword was found in the result), place this logic at this layer. This layer does NOT know anything about HTML, nor does it output it. It does NOT care about ADO or SQL, and it shouldn’t have any code to access the database or the like. Those tasks are assigned to each corresponding layer above or below it.

We must gain a very basic understanding of Object-Oriented Programming (OOP) at this time. Take time to read over http://searchwin2000.techtarget.com/sDefinition/0,,sid1_gci212681,00.html and make sure you understand the important benefits of OOP. To clarify, let’s look at another example, such as a shopping cart application. Think in terms of basic objects. We create an object to represent each product for sale. This Product object has the standard property getters and setters: getSize, getColor, setSize, setColor, etc. It is a super simple implementation of any generic product. Internally, it ONLY knows how to return information (getters) and understands how it can validate the data you pump into it (ONLY for its limited use). It is self-contained (encapsulation). The key here is to encapsulate all the logic related to the generic product within this object. If you ask it to "getPrice," it will return the price of the single item it represents. Also if you instruct it to "validate" or "save," it has the brains to be able to handle this, return any errors, etc.

We can plug this Product object into another object, a "Cart" object. This cart can contain and handle many Product objects. It also has getters and setters, but obviously on a more global scale. You can do something like "for each product in myCart", and enumerate (loop through) each product within. (For more information on enumeration, refer to http://www.m-w.com/cgi-bin/dictionary?enumeration.) Now, when you call "getPrice" for the Cart object, it knows that it must enumerate each product that it has, add up the price for each, and return that single total. When we fire the "saveCart" method, it will loop for each "product" and call its "saveProduct" method, which will then hit the Data Access Tier objects and methods to persist itself over to the Data Tier.

We could also take our simple Product object, and plug it into our "Sale" object. This Sale object contains all of the items that are available for a particular sale. And the Sale object can be used for things like representing all the items on sale at a given outlet or the like. I’m sure you are beginning to understand the advantage of using an OOP environment.

Data Access Tier

This layer is where you will write some generic methods to interface with your data. For example, we will write a method for creating and opening a Connection object (internal), and another for creating and using a Command object, along with a stored procedure (with or without a return value), etc. It will also have some specific methods, such as "saveProduct," so that when the Product object calls it with the appropriate data, it can persist it to the Data Tier. This Data Layer, obviously, contains no data business rules or data manipulation/transformation logic. It is merely a reusable interface to the database.

Conclusions

In all of the systems that I have been able to dig my dirty little hands into, I have rarely ever seen both the Business Tier and Data Access Tiers used. I mostly combine the two tiers. Allow the Business Layer to talk directly to the Data Layer, and do not bother with the Data Access Layer. To justify this, we are all developing on Internet time, and the last time I looked, it’s still going at about 3 to 4 times faster than normal time, which means we are expected to also work and produce at the same rate. The bottom line is reducing the time to market. In my opinion, writing this Data Access Tier, which is simply abstracting the Data Tier, is overkill, and ADO can be considered as this Data Access Layer. It provides us with the interface directly. We still keep all SQL in the Data Tier (stored procedures), but no business rules should be kept here.

Of course, the more tiers you add, the more performance is affected. The client hits "Save Cart" on their Web-enabled phone, it hits the Business Tier to call the "Cart" "saveCart," which calls the products "save," which goes either directly to the database or goes through the Data Access Layer and finally persists into the database. This path does affect performance. It is up to the application architect (you) to know and understand this, and all other factors affecting the system, and be able to make a good decision on how to develop it at this level. This decision is usually pretty easily made, depending on the amount of work and documentation that was produced from the analysis phase.

We all now know how to do this logically. Let’s explain the why. A good example is to look at the Presentation Logic Tier. Notice that many of its sections –the Web, the Proxy Tier, and the Client Interface — all sit directly on top of the Business Tier. We gain the advantage of not needing to redo any code from that Business Tier all the way to the database. Write it once, and plug into it from anywhere.

Now say you’re using SQL Server and you don’t want to pay Microsoft’s prices anymore, and you decide to pay Oracle’s instead. So, with this approach you could easily port the Data Layer over to the new DBMS and touch up some of the code in the Data Access Layer to use the new system. This should be a very minimal touch-up. The whole point is to allow you to plug each layer in and out (very modular) without too many hassles and without limiting the technology used at each tier.

Another example would be that we initially develop our entire system using VB (COM) and ASP, and now we want to push it over to our friendly VB .NET or C#. It is just a matter of porting the code over at each layer (phased approach), and voila, it’s done. (Microsoft has given us the ability for interop between classic COM and .NET.) We can upgrade each layer separately (with minor hurdles) on an as-needed basis.

The Future of Silverlight (source ::: Silverlight.net)

September 3, 2010 § Leave a comment

The Future of Silverlight

There’s been a lot of discussion lately around web standards and
HTML 5 in particular. People have been asking us how Silverlight fits
into a future world where the <video> tag is available to
developers. It’s a fair question—and I’ll provide a detailed answer—but I
think it’s predicated upon an oversimplification of the role of
standards that I’d like to clear up first. I’d also like to delineate
why premium media experiences and “apps” are better with Silverlight and
reveal how Silverlight is going beyond the browser to the desktop and
devices.

Standards and Innovation

It’s not commonly known, perhaps, that Microsoft is involved in over
400 standards engagements with over 150 standards-setting organizations
worldwide. One of the standards we’ve been involved in for years is HTML
and we remain committed to it and to web standards in general. It’s not
just idle talk, Microsoft has many investments based on or around HTML
such as SharePoint, Internet Explorer, and ASP.NET. We believe HTML 5
will become ubiquitous just like HTML 4.01 is today.

Standardize - Innovate But standards are only half of the story when we think of
the advancement of our industry. Broadly-implemented standards are like
paved roads.  They help the industry move forward together.  But before
you can pave a road, someone needs to blaze a trail. This is
innovation. Innovation and standards are symbiotic—innovations build on
top of other standards so that they don’t have to “reinvent the wheel”
for each piece of the puzzle. They can focus on innovating on the
specific problem that needs to be solved. Innovations complement or
extend existing standards. Widely accepted innovations eventually become
standards. The trails get paved.

In the past, this has happened several times as browsers implemented
new features that later became standards. Right now, HTML is adopting as
standards the innovations that came from plug-ins like Flash and
Silverlight. This is necessary because some of these features are so
pervasive on the web that they are seen by users as fundamentally
expected capabilities. And so the baseline of the web becomes a little
higher than it was before. But user expectations are always rising even
faster—there are always more problems we can solve and further
possibilities needing to be unlocked through innovation.

This is where Silverlight comes in. On the web, the purpose of
Silverlight has never been to replace HTML; it’s to do the things that
HTML (and other technologies) couldn’t in a way that was easy for
developers to tap into. Microsoft remains committed to using Silverlight
to extend the web by enabling scenarios that HTML doesn’t cover. From
simple “islands of richness” in HTML pages to full desktop-like
applications in the browser and beyond, Silverlight enables applications
that deliver the kinds of rich experiences users want. We group these
into three broad categories: premium media experiences, consumer apps
and games, and business/enterprise apps.

Premium Media Experiences

Examples include:

  • Teleconferencing with webcam/microphone
  • Video on demand applications with full DVR functionality and content protection like Netflix
  • Flagship online media events like the Olympics as covered by NBC, CTV, NRK, and France Télévisions
  • Stream Silverlight video to desktops, browsers, and iPhone/iPad with IIS Smooth Streaming

Even though these experiences are focused on media, they are true
applications that merge multiple channels of media with overlays and
provide users with full control over what, when, and how they experience
the content. The media features of Silverlight are far beyond what HTML
5 will provide and work consistently in users’ current and future
browsers. Key differentiators in these scenarios include:

  • High Definition (HD) H.264 and VC-1 video
  • Content protection including DRM
  • Stereoscopic 3D video
  • Multicast
  • Live broadcast support
  • (Adaptive) Smooth Streaming
  • Information overlays / Picture-in-picture
  • Analytics support with the Silverlight Analytics Framework

Consumer Apps and Games

The bar is continually rising for what consumers expect from their
experiences with applications and devices. Whether it’s a productivity
app or a game, they want experiences that look, feel, and work great.
Silverlight makes it possible for designers and developers to give the
people what they want with:

  • Fully-customizable controls with styles and skins
  • The best designer – developer workflow through our tools and shared projects
  • Fluid motion via bitmap caching and effects
  • Perspective 3D
  • Responsive UI with .NET and multithreading

Business/Enterprise Apps

As consumers get used to richer, better experiences with software and
devices, they’re bringing those expectations to work. Business apps
today need a platform that can meet and exceed these expectations. But
the typical business app is built for internal users and must be built
quickly and without the aid of professional designers. To these ends,
Silverlight includes the following features to help make rich
applications affordable:

  • Full set of 60+ pre-built controls, fully stylable
  • Productive app design and development tools
  • Powerful performance with .NET and C#
  • Powerful, interactive data visualizations through charting controls and Silverlight PivotViewer
  • Flexible data support: Databinding, binary XML, LINQ, and Local Storage
  • Virtualized printing
  • COM automation (including Microsoft Office connectivity), group policy management

Other Considerations

For simpler scenarios that don’t require some of the advanced
capabilities mentioned above, Silverlight and HTML both meet the
requirements. However, when looking at both the present and future state
of platform technologies, there are some other factors to take into
consideration, such as performance, consistency and timing.

Performance

The responsiveness of applications and the ability for a
modern application to perform sophisticated calculations quickly are
fundamental elements that determine whether a user’s experience is
positive or not. Silverlight has specific features that help here, from
the performance of the CLR, to hardware acceleration of video playback,
to user-responsiveness through multithreading. In many situations today,
Silverlight is the fastest runtime on the web.
Bubblemark

Consistency

Microsoft is working on donating test suites to help
improve consistency between implementations of HTML 5 and CSS3 but these
technologies have traditionally had a lot of issues with variation
between browsers. HTML 5 and CSS 3 are going to make this worse for a
while as the specs are new and increase the surface area of features
that may be implemented differently. In contrast, since we develop all
implementations of Silverlight, we can ensure that it renders the same
everywhere.
Browser Inconsistencies

Timing

In about half the time HTML 5 has been under design,
we’ve created Silverlight and shipped four major versions of it. And
it’s still unclear exactly when HTML 5 and its related specs will be
complete with full test suites. For HTML 5 to be really targetable, the
spec has to stabilize, browsers have to all implement the specs in the
same way, and over a billion people have to install a new browser or buy
a new device or machine. That’s going to take a while. And by the time
HTML 5 is broadly targetable, Silverlight will have evolved
significantly. Meanwhile, Silverlight is here now and works in all
popular browsers and OS’s.
Silverlight - HTML 5 Timeline

Beyond the Browser

In this discussion of the future of Silverlight, there’s a critical
point that is sometimes overlooked as Silverlight is still often
referred to—even by Microsoft—as a browser plug-in. The web is evolving
and Silverlight is evolving, too. Although applications running inside a
web browser remain a focus for us, two years ago we began showing how Silverlight is much more than a browser technology.

Silverlight Outside the Browser There are three areas of investment for Silverlight
outside the browser: the desktop, the mobile device, and the living
room. Powerful desktop applications can be created with Silverlight
today. These applications don’t require a separate download—any desktop
user with Silverlight installed has these capabilities. These apps can
be discovered and downloaded in the browser but are standalone
applications that are painless to install and delete. Silverlight now
also runs on mobile devices and is the main development platform for the
new Windows Phone 7 devices. Developers that learned Silverlight
instantly became mobile developers. Lastly, at NAB and the Silverlight 4 launch this year we showed how Silverlight can be used as a powerful, rich platform for living room devices as well.

Expect to see more from Silverlight in these areas especially in our
focus scenarios of high-quality media experiences, consumer apps and
games, and business apps.

When you invest in learning Silverlight, you get the ability to do
any kind of development from business to entertainment across screens
from browser to mobile to living room, for fun, profit, or both. And
best of all, you can start today and target the 600,000,000 desktops and
devices that have Silverlight installed.

If you haven’t already, start here to download all the tools you need to start building Silverlight apps right now.

For more information on this topic, you can watch a video with more details here.

Brad Becker, Director of Product Management, Developer Platforms

 

 

 

Where Am I?

You are currently viewing the archives for September, 2010 at Naik Vinay.