Saturday, December 09, 2006

OakLeaf Blog Gets Categories and Atom 1.0

I've just switched the OakLeaf blog to the new Blogger Beta version that supports categories, Atom 1.0 (finally), and RSS 2.0. All posts on and after June 13, 2006 have detailed categories (Blogger calls them Labels) collections at the end of the post, most of which duplicate the Technorati links. Earlier items have major category labels, such as LINQ or SQL Server. Categories let some RSS/Atom feed readers, such as Internet Explorer 7.0, filter items by category. The following screen capture shows IE 7 Feeds view's scrolling listbox with the LINQ to XSD label selected.

Note: One of the things I like about IE 7's Feeds view is that its chronology is based on Last Updated date/time, not the original post's date/time. This means that updated posts percolate to the top of the list; many of my posts are updated two or three times.

Here's Dare Obasanjo's three-pane, open-source RSS Bandit aggregator (Jubilee Edition Beta 1) displaying the preceding post:

Windows Live Writer (WLW) beta 1.0.1(6) works with Blogger Beta, as shown by the WYSIWYG screen capture below: Note: You must upgrade WLS to version 1.0.1(6) or later to work with Blogger Beta after early November 2006. However, WLW 1.0.1(6) doesn't support adding Blogger Beta Labels as tags. For the moment you'll need to do a final edit in the Web-based Blogger editor, which hasn't changed significantly in the Beta version. Technorati Tags: , , ,

Friday, December 08, 2006

PLINQ Gathers Momentum

Parallel Language Integrated Query or Parallel LINQ (PLINQ) finally emerged from the shadows with Microsoft Program Manager Joe Duffy's December 1, 2006 "A new role for me at Microsoft" post:

I recently left the CLR team to join a new team focusing on parallelism on Microsoft's platform in the 3-10 year timeframe. I am leading design and development of the Parallel LINQ (PLINQ) project that I alluded to here.

We're looking for supersmart technical people to join the team and help change the face of programming for anybody writing code on the CLR or VC++. PLINQ isn't the only project. Solid CS skills are a must, but you don't necessarily have to be a concurrency guru (right away).

These [22] job postings have some detail. If something catches your eye, respond on the jobs site or send me your resume directly at joedu AT you-know-where DOT com (i.e. microsoft DOT com).

I'll of course still be blogging about everything concurrency related, so you won't notice much of a difference content-wise. And I'm still happy to answer any CLR related questions and help you find the right folks inside the team to listen to your feedback.
Joe is the author of an MSDN Magazine January 2006 "{END BRACKET}" column, "Transactions for Memory," and September 2006 "CLR Inside Out" column, "Using Concurrency for Scalability." There's no mention of LINQ in either article, but the handwriting was on the wall.

The first concrete information about PLINQ came from an August 28, 2006 eWeek article, "Microsoft's PLinq to Speed Program Execution," by Darryl K. Taft, who quotes Anders Heljsberg:

"With PLinq, effectively you write the code the same way, but we arrange for it to run on multiple CPUs," Hejlsberg said in an interview at Microsoft in early August. "So the queries get split up and run on multiple CPUs, and then you just wait for all the results to arrive. And lo and behold, without any changes your program just ran six times faster. It's instant gratification. ...

"It doesn't necessarily mean that every program is going to run six times faster, but there are classes of programs that we can make run faster without the user having to get into the nitty-gritty business of writing concurrent constructs."

Danny Thorpe, formerly Borland's Chief Scientist and now Microsoft Sr. Product Manager/Architect, noted in a September 2005 blog post announcing Borland's Delphi would support LINQ, that LINQ had parallel computing potential. Taft's September 27, 2005 eWeek article, "Borland Plans to Support MS LINQ in Delphi Platform" quotes Danny:

"LINQ presents an enormous opportunity to put parallel computing in a package that everyday coders can use safely and easily. Exploit those multicore processors! Even qrid computing is within reason."

I don't usually write about projects that don't have at least at least a public preview or alpha version available for testing. However, it appears that Microsoft is staffing to deliver PLINQ in the Orcas timeframe. So following the PLINQ story looks worthwhile.

Don Domsak's recent Parallel Language Integrated Query (PLINQ) post adds fuel to the PLINQ fire with this conclusion:

Overall, this stuff looks very cool. And it seems that LINQ is going to be a big part of how they plan to implement it, giving me even more of a reason to get going on LINQ before all the cool kids realize that WPF, WCF and WF are yesterday's news, and LINQ is where it is at ;).

Note: Don Domsak, better known as DonXML is a Microsoft MVP for XML and a VB .NET fan. Don recently gave presentations on LINQ and the Entity Framework at the Heartland Developer Conference (HDC) 2006.

Question of the day: Will the PLINQ moniker morph to initial-letter-capped Plinq (a la Blinq), PLinq (per the original DLinq and XLinq API names), or adopt the LINQ to Whatever style as LINQ to Cores?

Update: 7/30/2007: Mary Jo Foley posted What will next-generation multicore apps look like? today, which quotes the presentation that Craig Mundie, Microsoft's Chief Research and Strategy Officer, gave to last week's Financial Analysts Meeting. There's no mention of PLINQ in the transcript that Mary Jo cites or the PowerPoint slides. It's surprising that PLINQ wasn't part of the presentation because it's probably Microsoft's first concrete implementation of declarative languages for multi-core processing.

Update 1/23/2007: Joe Duffy updated his post about PLINQ talk at the Declarative Aspects of Multicore Programming (DAMP) workshop he gave at POPL 2007 earlier in January by adding a link to his slides.

Update 12/12/2006: Anders Hejlsberg discusses PLINQ, concurrent programming, and LINQ for Orcas in an 8:29 interview from Tech•Ed: Developers 2006 Barcelona. The page also includes links to Eric Rudder's 1:15:00 Windows Vista, 2007 Office System and AJAX keynote, and brief interviews with Scott Guthrie, Paul Andrew, and Keith Smith.

Technorati Tags: Orcas, PLINQ, LINQ, C# 3.0, VB 9.0

Thursday, December 07, 2006

Reduce Object/XML Impedance Mismatch with LINQ to XSD

LINQ to XSD from Microsoft's XML Team promises a similar reduction of the impedance mismatch between .NET objects and XML documents as LINQ to Entities and ADO.NET 3.0's Entiry Framework and Entity Data Model deliver for objects and relational data.

LINQ to XSD, which entered the public preview state on November 27, 2006 with the release of the Alpha 0.1 version, builds on LINQ to XML's generic XML trees to operate on typed XML trees, which are "instances of .NET types that model the XML types of a specific XML schema (XSD)." Thus LINQ to XSD carries the subtitle "LINQ to XML Objects."

Note: If you don't want to download the preview bits, which require the Microsoft .NET LINQ CTP (May 2006), read the "LINQ to XSD Overview: An Incubation Project on Typed XML Programming" white paper.

Updated: February 7, 2008

A First Look at LINQ to XSD Syntax

The XML Team's blog post and documentation for the LINQ to XML preview cites this prototypical LINQ for XML query that returns the total value of Item elements in in a purchaseOrder document:

(from item in purchaseOrder.Elements("Item") select (double)item.Element("Price") * (int)item.Element("Quantity")).Sum();

Here's the strongly typed LINQ to XSD version of the preceding query:

(from item in purchaseOrder.Item select item.Price * item.Quantity ).Sum();

Obviously, the type-safe version of the query's syntax is clearer. It also provides Intellisense for elements and corresponds more closely to a LINQ to SQL query against a purchaseOrder table with a related Item table.

Aside from the obvious syntatical benefits and compile-time vs. run-time syntax checking, LINQ to XSD supports contract-first rather than code-first development. Many Web services developers are contract-first devotees, but Dare Obasanjo—one of Microsoft's foremost XML/XSD gurus—recommends the code-first approach in his April 22, 2005 "Contract-First XML Web Service Design is No Panacea" post.

Note: Click here for a list of Dare's technical papers, articles, and other writings as of May 2005.

LINQ to XSD can handle code-first (or, more properly, document-first) design by inferring and refining XML schemas from existing XML documents with the Microsoft XSD Inference 1.0 tool. My "Generate XSD Schemas by Inference" article for the November 2002 issue of XML Magazine explains how to get the most out the tool. (Free registration is required to read page 2 through 4).

O/X Impedance Mismatch Background

My September 25, 2005 post, "More on Object-XML and Object-Relational Impedance Mismatch," cited Dare's "The Impedence Mismatch between W3C XML Schema and the CLR" post, which discusses XML serialization of object state and conversion of XML to objects. Dare suggests his earlier "XML Schema Design Patterns: Is Complex Type Derivation Unnecessary?" post and the "Programming with Circles, Triangles and Rectangles" paper by Gavin Bierman, Wolfram Schulte and Erik Meijer for more details on X/O impedance mismatch issues. This paper extends an earlier presentation to the Workshop on Declarative Programming in the Context of OO Languages (DP-COOL) 2003—Unifying Tables, Objects and Documents by Eric Meijer and Wolfram Schulte.

Note: The BSM trio also presented "LINQ: Reconciling Objects, Relations and XML in the .NET Framework" to SIGMOD 2006. Unfortunately, only the first page is available for download.

Apparently, Erik and his colleagues are sanguine that the longstanding issues with X/OM (XML-to-Object mapping) can be resolved. He and Data Progammability Team program manager Ralf Lämmel authored "Revealing the X/O Impedance Mismatch" (July 19, 2006 draft) for submission to and possible publication in the post-proceedings for Datatype Generic Processing (DPG '06), Lecture Notes in Computer Science (LNCS, Springer US). The paper begins with an excerpt from Dave Thomas's "The Impedance Imperative: Tuples + Objects + Infosets = Too Much Stuff!" article for the September-October 2003 issue of the Journal of Object Technology.

Another paper, "Mappings make data processing go ’round: An inter-paradigmatic mapping tutorial," by Erik and Ralf (2005) starts with the same Dave Thomas quotation. The abstract describes the tutorial's objective:

Each data-processing application depends on a horde of interrelated data models and artifacts that are derived from data models (such as data-access layers). Such conglomerations of data models are challenging due to paradigmatic impedance mismatches, performance requirements, loose-coupling requirements, and others.

This ubiquitous problem calls for a good understanding of techniques for mappings between data models, actual data, and operations on data. This tutorial lists and discusses mapping scenarios, mapping techniques, impedance mismatches and research challenges regarding mappings. [Emphasis added].

Note: Dave Thomas and Erik Meijer are speakers for the QCon Conference to be held March 12 - 16, 2007 in London. Erik and Martin Fowler are among the conference's keynoters.

Ralf presented two papers at XML 2006 on December 5, 2006: "Typed XML programming without abandoning XML" (a.k.a. "Functional OO Programming with Triangular Circles" with Dave Remy as co-author) and "XML streaming, XML trees and XML queries—Can they co-exist in harmony?" (by Michael Champion). Mike chaired the Enterprise XML Computing sessions and provides a blow-by-blow description of the December 5 and part of the December 6 sessions in his XML 2006 Observations post.

Note: Dave Remy said on June 16, 2006: "I am now working hands on a very cool XML developer tool (can't say specifically what quite yet) that uses WPF (also known as Avalon) and XLinq extensively. I look forward to doing some future blogs in these areas." (To my knowledge, no future blogs on the topic appeared as of early 2008.)

Charting the Course of LINQ to XSD in Orcas

The more general tutorial, "Mappings make data processing go 'round—An inter-paradigmatic mapping tutorial," "... lists and discusses mapping scenarios, mapping techniques, impedance mismatches and research challenges regarding mappings" with the emphasis on O/RM and X/OM. This paper is included in the Summer School Proceedings of the Generative and Transformational Techniques in Software Engineering (GTTSE) 2005, of which Ralf was an organizer.

Ralf offers the "XML Typed Programmer" quartet with the following posts, some of which are quite detailed (i.e., lengthy):

Note: The current LINQ to XSD implementation is C# 3.0 only, which is surprising when you consider Erik's penchant for Visual Basic and his recent VB IsNot C# seminar at Expo-C 2006.

Tech support for LINQ to XSD is from the XML and the .NET Framework newsgroup, not the expected LINQ Project General newsgroup.

LINQ to XSD is an "incubator" project and the preview comes with a "While the underlying LINQ to XML technology is expected for Orcas, no such commitment exists for LINQ to XSD" caveat. But it seems to me that LINQ to XSD is a necessary addition to mainstream LINQ to SQL (formerly DLinq) and LINQ to XML (formerly XLinq) APIs, and developing LINQ to Entities and LINQ to DataSets technologies. Without LINQ to XSD, the final Orcas LINQ implementation will be incomplete.

Updated: 12/8/2006 and 12/11/2006 Minor additions and corrections. Reformatted: 2/7/2008.

Technorati Tags: LINQ to XSD, LINQ to XML Objects, LINQ to XML, XLinq, C# 3.0, VB 9.0, XML, XSD, XML Schema, Orcas, Domain-Specific Languages, DSL, DSL Tools

Saturday, November 25, 2006

Orcas December 2006 CTP Coming with New LINQ/EDM Bits

Visual Studio Orcas CTPs will replace ADO.NET vNext CTP drops starting with the Orcas December 2006 CTP. Charlie Calvert, Microsoft's Community Program Manager for the C# group, reports in his November 21, 2006 Community Convergence XII post:

The Orcas December CTP will contain new LINQ bits. The team has been churning out daily builds filled with new LINQ content. Over the next weeks it will all come together in a CTP that will be released to the public. This will be the first major update to the LINQ bits since the May CTP. The first Orcas beta is not due until 2007.
Charlie's post follows ADO.NET Technical Lead Pablo Castro's November 7, 2006 ADO.NET Orcas and Samples item:

As we make progress on the Orcas release of Visual Studio, the various teams—including ourselves—are working hard at integrating everything in a single product, Visual Studio Orcas. For the ADO.NET Entity Framework this means that you won’t see component-specific CTPs any more for Orcas, and instead you’ll see Orcas CTPs that have all these technologies incorporated. We may still do separate CTPs of related technologies if we see that it would help at some point in time.

Also, since the ADO.NET Entity Framework is in the Orcas builds, we don’t need the generic “vNext” token for it; from now on we’ll refer to it simply as ADO.NET Orcas, which will include the ADO.NET Entity Framework and LINQ to ADO.NET in its various flavors (LINQ to DataSet, LINQ to SQL and LINQ to Entities).

The December CTP release undoubtedly will integrate updated versions of the the ADO.NET Entity Framework from the October 2006 Orcas CTP and its sample code plus the the August 2006 ADO.NET vNext CTP's Entity Data Model (EDM) designer prototype.


Here's the latest (December 8, 2006) update on the Orcas December CTP 2006 release from the Visual C# Community Center:
The December Orcas CTP will be released soon. This CTP will be a regular install, and will not ship inside a Virtual Machine. It will co-exist with Visual Studio 2005. The main feature in the CTP will be the ability to work with LINQ. These will be the first new LINQ bits we have seen since the May CTP. The December CTP is a pre-beta release. The Orcas Beta is not expected until sometime in 2007. The team is also near the release of Service Pack 1 for Visual Studio 2005. Right now, I'm still exploring this issue, but I've heard that the order in which we install Service Pack 1 and the LINQ May CTP may be important. The reports I'm hearing at this time suggest that we should install the service pack first, and then the May CTP. I should have more information on this issue by the end of the week.

I believe Charlie meant "December CTP" where he mentions "May CTP" in the preceding paragraph.


Charlie has posted the first four five installments of The LINQ Farm, a series of articles for beginning LINQ C# programmers:

  1. LINQ for Beginners (10/29/2006)
  2. Query Expressions (10/31/2006)
  3. Query Operators (11/11/2006)
  4. Using Distinct and Avoiding Lambdas (11/19/2006)
  5. Focus on Grouping (12/2/2006)

He avoids deep discussions of lambdas, which makes the articles useful for VB developers also. Charlie points to a video and some recent articles of interest to LINQ and ADO.NET EF developers:

Here are a few links to recent Channel9 videos that might interest LINQ developers:

Updated: 12/7/2006 with Charlie Calvert's fifth episode of the LINQ Farm: Focus on Grouping. 12/8/2006 for potential Orcas issues with VS 2005 SP1.

Technorati Tags: Orcas, ADO.NET vNext, Entity Framework, Entity Data Model, LINQ, LINQ to Entities, LINQ to DataSets, LINQ to SQL, Entity SQL, eSQL, DLinq, XLinq, C# 3.0, VB 9.0, ObjectSpaces, Domain-Specific Languages, DSL, DSL Tools

Wednesday, November 15, 2006

Microsoft Offers SQL Server 2005 SP2 CTP

Microsoft announced on November 7, 2006 the availability of a Communtity Technical Preview (CTP) of the forthcoming SQL Server 2005 Service Pack 2 for all editions except Express, and special SP2 CTPs for the Express edition (SQLX) and Express with Advanced Features. SP2 will be required to run any version of SQL Server under Windows Vista and "Longhorn" Server. The "What's New in SQL Server 2005 SP2" page summarizes upgrades to:

  • Analysis Services
  • Database Engine
  • Integration Services
  • Reporting Services and
  • SharedTools
for editions that incorporate the features. Download the appropriate SP2 CTP bits from the SQL Server Community Technology Preview Program page. Microsoft senior vice president of Data and Storage Platforms Paul Flessner expanded on the preceding list during his keynote speech at the 2006 Professional Association for SQL Server (PASS) Community Summit in Seattle on November 15, 2006. Added features include:
  • Data compression
  • Increased business intelligence functionality
  • Security updates relating to Common Criteria
  • Manageability enhancements
  • Support for Windows Vista and
  • Optimization for use in the 2007 Microsoft Office system environment
Microsoft is pursuing Common Criteria security certification for SQL Server 2005 Enterprise Edition SP1 and SP2. Many governments require Common Criteria certification and it's a preference or requirement for many industries. In the meantime, Microsoft has made available Enterprise Strategy Group (ESG) reports on SQL Server 2005 security—Microsoft SQL Server Runs the Security Table and The Security Development Lifecycle (SDL). Advantage, Microsoft. According to ESG, "Microsoft SQL Server 2005 is particularly worth examining as it is the first major product release that Microsoft has put through the SDL." Flessner also announced that Visual Studio Team Edition for Database Professionals (formerly code-named "DataDude") is set to RTM on November 30, 2006.

Updated: 11/16/2006 with additional security data.

Technorati tags: , , , , , , ,

Thursday, November 09, 2006

ADO.NET Sync Framework for Occasionally Connected Systems

WiFi Internet connectivity is becoming ubiquitous in first-world urban areas, but there are classes of data collection/management applications that must be operable during wired and/or wireless network outages—emergency and health services, for example—or exhibit dramatically decreased user productivity without a live network connection—field sales workers come to mind. Some occupations are inherently occasionally connected: governmental, academic, and corporate field workers in rural locations; land surveyors; forest rangers; environmental scientists; marine biologists and the like. Seldom, occasionally, and usually-connected users need the ability to cache data locally and synchronize local data with large back-end databases. The preferred caching and synchronization model is Outlook 2003/2007, where clients always work with their local data store and the server only propagates data changes to the client. Following are the most common methods of client-side caching and synchronization:

  • ADO.NET Datasets persisted as XML files
  • Remote Data Access (RDA) for SQL Mobile/SQLce databases
  • Merge replication to SQL Server 2005 (not Express)
  • Occasionally Connected Systems (OCS)Sync Framework (future)
ADO.NET Datasets Microsoft's developers designed ADO.NET Datasets to support data management applications for usually, occasionally, or seldom-connected mobile users. Datasets persist dynamic (read/write) and a subset of catalog (read-only, slowly changing) relational data in XML files. Datasets replace combinations of merge and snapshot replication with a lighter-weight, XML file-based system that uses DataAdapters to communicate with back-end RDBMSes. I described disk and RAM resource consumption issues with large ADO.NET 1.1 and 2.0 Datasets in my May 2004 "Store Large Lookup Tables in DataSets" article for Visual Studio Magazine (reading page 2 requires free registration.) The article's Table 1 shows the time to load Datasets of various sizes from XML files Although multi-MB Datasets are practical for today's laptop, tablet, and ultra-mobile (portable) PCs, their resource consumption precludes use on Windows CE, PocketPC, SmartPhone, and similar devices. Single-file relational databases, such as SQL Server 2005 Compact Edition (SQLce), are better suited than Datasets for portable PCs and devices when data storage requirements exceed a few MB. Remote Data Access RDA is the basic application for synchronizing data between SQL Server Mobile or, more recently, SQLce—formerly called SQL Server Everywhere (SQLEv). RDA pulls data from a remote SQL Server 2000 or 2005 table to a client's SQLce table. The SQLce database keeps track of changes changes to the pulled data and, on demand, pushes the changes to the back-end server. RDA also can execute CRUD (CREATE, RETRIEVE, UPDATE, and DELETE) operations on the remote server with Transact-SQL (T-SQL) statements. SQL Server doesn't push changes in its data to SQLce; thus, RDA is a one-way replication technology.

RDA connects to the back-end database with the HTTP or HTTPS protocols to Internet Information Services (IIS) on the server and pass compressed data through firewalls. Custom C#/VB code or the Connection Manager application handles the details of the connection. RDA is the only method of replicating data between SQL Server 2005 Express (SQLX) and SQLce, because SQLX (unlike MSDE 2000) isn't a merge replication publisher. RDA can detect but doesn't handle concurrency or referential integrity conflicts, and schema changes aren't allowed.

Merge Replication Replication is the traditional means of updating data between SQL Server instances, and merge replication is the most common type. Merge replication uses a different Connection Manager to handle communication with the back-end database using HTTP or HTTPS protocols to pass compressed data through firewalls. Merge replication is two-way, supports referential integrity, handles concurrency conflicts, and allows schema changes. Merge replication, including subscription and publication, is a heavyweight process compared to RDA push/pull operations, but is quite reliable. OCS Sync Framework The OCS Sync Framework involves a SyncAgent on the client that uses a SyncTable to manage a ClientSyncProvider for each type of local store, such as SQLce or SQLX. Server-side components include a ServerSyncProvider, SyncGroup, SyncAdapter, and SyncAdapter commands. The SyncAdapter and SyncAdapter commands (DBCommand objects) are ADO.NET database-agnostic objects so synchronization can occur with SQL Server, Oracle, IBM DB2 or any other RDBMSes that have an .NET native data provider. IncrementalInserts, IncrementalUpdates and IncrementalDeletes enable clients to request the server to update catalog data. The client and server can push changes directly with SQL Server TDS or another RDBMS's wire protocol when a physical network connection is available. Otherwise the client can push and pull changes with a proxy that connects to a service. Synchronization methods can be:
  • Pull only from server (unidirectional)
  • Push only to server (unidirectional)
  • Push and pull (bidirectional)
  • Snapshot (no synchronization)

The OCS Sync Framework appears to fall midway between the lightweight RDA and heavyweight merge replication method in operational complexity and resource consumption, but the current (very early) implementation requires a substantial amount of client code to specify synchronization type and SQL statements for DBCommands.

Live From Redmond: Smart Client: Offline Data Synchronization and Caching for Smart Clients is Steve Lasker's 94-minute Webcast that covers Dataset, RDA, merge replication, SQL Query Notifications, and a preview of the OCS Sync Framework (requires free registration). Steve is a Microsoft program manager/technical lead and informal evangelist for OCS, Windows forms, VB .NET, and ADO.NET Datasets. Steve also delivered a more general Live From Redmond: Visual Studio: Developing Local and Mobile Data Solutions with SQL Server Compact Edition Webcast on December 4. Steve also offers an Occasionally Connected Systems slide deck and a screencast that demonstrates how the OCS Sync Framework operates and VB WinForm code to synchronize a client with SQL Server. Most public OCS-related information presently comes from Steve's blog. His "Tech Ed 06 Slides and Demos on SQL Server Everywhere Edition" post has links to DEV351: Developing Local and Mobile Data Solutions with SQL Server Everywhere Edition and DEV343: Offline Data Synchronization and Caching with SQL Server Everywhere Edition.

Update: 12/9/2006: 12/4/2006 Webcast name updated.

Technorati tags: , , , , , , , , , , , , ,

Wednesday, November 08, 2006

SQL Server 2005 Compact Edition RC1 Available

Microsoft accounced on November 7, 2006 the availability of SQL Server [2005] Compact Edition (SQLce) 3.1 Release Candidate 1 (RC1). SQLce—formerly named SQL Server Everywhere Edition (SQLEv) 3.1—is a lightweight, in-process cousin of SQL Server 2005 and SQL Server 2005 Express. SQLce is the successor to earlier SQL Server Mobile 3.0 and SQL CE 2.0 and 1.0 editions. You can download the SQLce RC1 runtime and readme, as well as SQLce RC1 Books Online. SQLce is an embeddable, small-footprint, single-user database for mobile and desktop applications. As an example, you can substitute SQLce for SQL Server 2005 Express (SQLX) when you need local storage for usually, occasionally or seldom-connected systems. SQLce uses the ADO.NET programming model, supports most SQL Server 2005 data types and T-SQL reserved words, and is freely distributable.

According to the "Microsoft SQL Server 2005 Compact Edition Overview" white paper, SQLce:

  • Occupies only 1.8 MB of disk space
  • Supports single-file databases up to 4 GB in size
  • Uses 128-bit SSL for secure and reliable functionality, even through firewalls
  • Uses 128-bit RSA file-based encryption on devices for database file security
  • Provides an encrypted data format with password protection
  • Will use the ADO.NET Sync Framework in Visual Studio vNext ("Orcas")

A separate OakLeaf blog post, "ADO.NET Sync Framework for Occasionally Connected Systems" has the details on Microsoft's new approach to SQLce synchronization that's coming in Orcas.

I wrote about Mobile Edition's morph to Everywhere Edition in my May 1, 2006 "SQL Server 2005 Mobile Edition Goes Everywhere" article for Fawcette Technical Publications Online's "Special Report: SQL Server." "SQL Everywhere" had a "déjà vu all over again" ring to me. It appears that I wasn't the only one non-plussed about the "Everywhere" suffix, which appeared to me to encroach on Sybase's SQL Anywhere trademark for a similar database product. Sybase also claims here that SQL Everywhere is their trademark. Here's what Microsoft has to say about renaming SQLEv to SQLce:

SQL Server 2005 Compact Edition, was previously named SQL Server 2005 Everywhere Edition during the product development phase. Customers have communicated to Microsoft through the pre-release community technology preview (CTP) program and other channels that this product name may cause potential confusion with other database product names in the industry. Microsoft has taken this feedback seriously and has accordingly changed the official product name.
Of course, this isn't the first time that Microsoft has done an about-face on product and architecture names. Remember .NET Everything? Steve Lasker's "SQL Server Everywhere Gets a New Name" post has more to say about the name change and SQLce's features in the forthcoming RTM bits. Steve is a Microsoft program manager/technical lead for Occasionally Connected Systems (OCS) and the forthcoming ADO.NET Sync Framework. Steve's Live From Redmond: Visual Studio: Developing Local and Mobile Data Solutions with SQL Server Compact Edition December 4, 2006 Webcast provides a detailed overview of SQLce's capabilities. His presentation includes a substantial amount of VB (!) ADO.NET code. (Free registration required.) Several comments about the post complain about SQLce's 4 GB size limit, which is a significant problem for local document storage. In a reply to a comment by John, Steve says, "Again, the current 4gb limit is purely a device optimization that we will definitely remove now that we’re running on larger desktop scenarios. ... The 4gb limit isn’t a 'free' restriction as we’ve done with Express." Microsoft's product page for SQLce hadn't been updated from SQLEv to SQLce terminology when this post was written. If you're working with the SQLEv CTP on devices, you can download the CTP for SQLEE Access Database Synchronizer to synchronize data between Access 2000 - 2007 databases and SQLEv CTP or SQLce RC1. There's more information on all these topic, plus details for the Microsoft SQL Server 2005 Compact Edition Tools for Visual Studio SP1 Beta, which Microsoft says updates the VS 2005 SP1 Beta smart device development components with the design time environment for SQLce, at the SQL Server Everywhere Edition [sic] blog. The SQLce newsgroup is here.

Updated 11/9/2006 with additional details about and links to SQLce, SQLEv, OCS and Sync Framework topics. 12/9/2006: Added 12/4/2006 Webcast link.

Technorati tags: , , , , , , , , , , , , ,

Wednesday, November 01, 2006

Objectify Data with ADO.NET vNext

The "Objectify Data with ADO.NET vNext" article from the October 2006 issue of Visual Studio Magazine explains how the ADO.NET vNext August 2006 Community Technical Preview reincarnates ObjectSpaces’ object/relational mapping (O/RM) technology and OPath query language as the Entity Framework (EF), Entity Data Model (EDM), Entity SQL (eSQL), and LINQ to Entities for the Visual Studio “Orcas” release. Here's a screen capture of the article's VB 9.0 sample test harness: The article's AdventureWorks SalesPersons bonus project (AWv3TestApp.sln) invokes the AdventureWorksV3 EDM class library to populate a DataGridView with records for sales personnel who are eligible for bonuses—five years employment by AW for this example. Clicking the Add or Deduct buttons increcments or decrements bonuses, persists the changes, and refreshes the grid. If you're interested in learning more about the ADO.NET team's new approach to O/RM check out these previous OakLeaf posts:

Click here for a page of links to earlier posts about LINQ, LINQ to SQL (DLinq), and LINQ to XML (XLinq)

Technorati Tags: ADO.NET vNext, Entity Framework, Entity Data Model, LINQ, LINQ to Entities, LINQ to DataSets, LINQ to SQL, Entity SQL, eSQL, DLinq, XLinq, C# 3.0, VB 9.0, Orcas, ObjectSpaces, Domain-Specific Languages, DSL, DSL Tools

Tuesday, October 31, 2006

Microsoft Offers Free SQLX-Based Accounting App

Microsoft Office Accounting Express (MOAX) 2007 is an entry-level accounting package targeted at small businesses whose proprietors use paper-and-pencil or Excel as their basic bookkeeping tools. What's unique about MOAX is it's license fee: US$0.00. Product activation requires registration with full company name and address plus contact details, but Microsoft doesn't require your Federal Employer ID (or Social Security) number. Microsoft RTM'd MOAX on October 29. You can download MOAX here (338 MB), read Mary Jo Foley's "Microsoft introduces a new freebie" blog post, and learn more about MOAX features from the Office Accounting home page. Here's an 800x600 capture of MOAX's invoice entry form. MOAX offers integration with Business Contact Manager (BCM) for Outlook, Excel for PivotTables and PivotCharts, and Access for reports. (The Access reporting feature didn't work for me with Access the 2007 Beta 2 Technical Refresh.) OfficeOnline provides secure file transfer to and from the firm's CPA. Third-party add-ins include:

  • Office Online Marketplace eBay auctions (80 free or $9.95 for 200 listings per month)
  • ADP payroll processing ($169/year)
  • Equifax credit reports ($39.95 each and up)
  • Chase Paymentech credit-card processing ($9.95/month)
  • PayPay payment processing ($9.95/month + bank processing $20/month)

Note: Pricing above is from Mary Jo Foley's blog post.

Wizards streamline importing data from Intuit QuickBooks or Microsoft Money to MOAX. MOAX's primary limitation is lack of inventory maintenance features.

Here's one of the sample companies' customer list. Notice the similarity of the left pane to Outlook's Navigation Bar and Access 2007's Navigation Pane.

MOAX uses SQL Server 2005 Express edition (SQLX) as its back end, so the data store is robust and reliable. The 584 table names for a single company are plain English. The same is true for the 1,793 T-SQL stored procedures, 538 views, 260 T-SQL scalar functions, 56 T-SQL inline table-valued functions, 47 T-SQL table-valued functions, 825 T-SQL DML triggers, 643 foreign-key constraints, and 1,065 check constraints. Thus, it's no surprise that a a new company database I created (oakleafsystems.sbd) weighed in at 68.6 MB for starters. Notes: Exploring the sys.objects catalog view disclosed no .NET CLR aggregate functions, stored procedures, or scalar, table-valued or inline table-valued functions. If you've installed SQLX locally, you can opt to use your current instance instead of the \MSSMLBIZ instance included in the download. MOAX substitutes .sbd for .mdf and .sbl for .ldf extensions for data and log files, respectively. Microsoft's Office 2007 system requirements are a 500MHz+ CPU and 256 MB RAM (1 GHz+ CPU and 1 GB RAM for Outlook with BCM). Most users will find MOAX sluggish with CPUs slower than 2.5 GHz, and less than 1 GB RA. Microsoft encourages users to upgrade to the forthcoming $149 Microsoft Office Accounting Professional (MOAP) 2007, which replaces the underpowered Small Business Accounting 2006 product. PC Magazine offers a full review (10/2/2006) of a late MOAP beta, which concludes, in part: "Microsoft's Office Accounting 2007 beta is a vast improvement over last year's edition. It should prove an effective tool for small businesses that don't have large-scale inventory requirements." MOAP competes directly with QuickBooks Premier Edition 2007 ($325 - $350) and Peachtree Premium Accounting 2007 ($450 - $470). Here's a MOAX customer editing form: MOAP provides full multi-user access with Small Business Server, supports inventory maintenance, multiple currencies, and provides additional customizable reports. MOAX users must upgrade to MOAP to connect to a remote SQLX or SQL Server 2005 instance.

Technorati Tags: Microsoft Office Accounting Express 2007, Office Accounting Express 2007, Microsoft Office 2007, SQL Server 2005 Express, MOAX 2007, MOAX, SQLX

Wednesday, October 04, 2006

New Entity Data Model Graphic Designer Prototype

Microsoft's ADO.NET vNext team posted on MSDN the code for the first Entity Data Model (EDM) Designer Prototype CTP on September 27, 2006. Pablo Castro demoed this prototype in his September 1, 2006 "ADO.NET Entity Framework: What. How. Why." Channel 9 video. The video coincided with the release of the ADO.NET vNext August 2006 CTP, which is an EDM Designer prerequisite.

The accompanying Readme.htm and Overview.doc files make it clear that this EDM Designer release is indeed a prototype. The Designer has the capability to generate the initial storage schema (SSDL file), mapping layer (MSL file), conceptual layer schema (CSDL file), and C# or VB class code from an SQL Server database. The designer only manipulates the CSDL file. If you alter the data model at the CSDL level or change property values of Entity Types, Entity Sets, Associations, or Association Sets, you must manually edit the MSL file and, in some cases, the SSDL file.

Most EDM code examples use one or two entities from the AdventureWorks sample database and simple associations. Here's Visual Studio 2005 displaying a diagram of the complete Northwind sample database (Access version) with the Entity Container and Entity Type elements rearranged but before making changes to Entity Set/Type names:

Click images to display in full size (800 x 600). Click here for a Web page with more images.

Here's the complete diagram exported by the Designer to a JPEG file:

Notice that Associations replace Entity Type foreign key properties, such as Orders.CustomerID, Orders.EmployeeID, and Orders.ShipperID.

The Designer inherits limitations of the ADO.NET vNext August 2006 CTP: No support for SQL Server's text, ntext, or xml data types (Employees.Notes, Products.HomePage, and Categories.Description fields), or Associations for tables with composite primary keys (Line Items). Therefor, FK_Order_Details_Orders and FK_Order_Details_Products Association lines are missing in the preceding diagram and Order_Details entities aren't updatable.

Changing Entity Type, Entity Set, and Association Names

The prototype Designer doesn't offer an option to singularize plural table names as Entity Type names. Changing Entity Type, Entity Set, Association, and Association Set names in the designer is easy, but making the requisite edits to the MSL and SSDL files isn't a walk in the park. Search and replace works for most name changes, but the CSDL file often loses the 63 suffix that distinguishes the two Employees/Employee endpoints after editing other names. You'll also encounter issues with entity or property names that conflict with C# or VB reserved words, such as Order in VB.

Here's the JPEG diagram of the preceding diagram with Entity Type names singularized, the Orders Entity Set renamed to SalesOrders, and Order Details changed to LineItems.

Notice that cardinality of the Employee.EmployeeID:Employee.ReportsTo Association in the preceding screen capture was mistakenly changed from 0..1:0..* (one-to-many) to 0..1:0..1 (one-to-one with nulls allowed) manually. The cardinality was later returned to that generated from the database, but the values in the diagram didn't change to conform the updated setting.

Testing Associations, Deferred Loading, and MARS

After changing Association names in the schema and mapping files, it's a good idea to verify that the renamed Associations continue to correspond to table relationships. This requires a more sophisticated test harness than the C# console demo projects favored by the ADO.NET vNext team. You need a grid to view properties of multiple entities and their associated foreign key values or counts of related entities.

Fortunately, you can populate a DataGridView control directly by setting its DataSource property value to a ageneric List generated by applying the ToList() method to the Entity Set returned from a LINQ to Entities query:

Dim Orders = From so In edmNwind.SalesOrders _
  Select so _
  Order By so.OrderID Descending
Dim lstOrders As List(Of SalesOrder) = _
  Orders.ToList
With dgvList
  .Columns.Clear()
  .DataSource = lstOrders
  .Columns.Add("CustomerID", "CustomerID")
  .Columns.Add("EmployeeID", "EmployeeID")
  .Columns.Add("ShipVia", "ShipVia")
End With

Additional code populates the added columns with the foreign key values. Unfortunately, the position sequence of all but the added columns have no relationship to their ordinal value in the table or their sequence in the Entity Type definition. The ADO.NET vNext team intends to improve databinding with, perhaps, a ToBindingList() method or wrapper.

Associations have the GetEntityTypeName() method to return a single related entity and the GetEntityTypeNameRef() method to return a reference to an entity. Like LINQ to SQL (DLinq), the Designer "lazyloads" related entities; that is, the entities aren't retrieved unless or until your code requests them. DLinq has the Including() operator to return related instances such as SalesOrder.Customer or Product.Category. The EDM requires you to load related entities explicitly with a procedure such as:

Public Sub GetCustomerIDForSalesOrder(ByVal so As SalesOrder, _
    ByVal intRow As Integer)
  If Not FK_SalesOrders_Customers.GetCustomerRef(so).IsLoaded Then
    FK_SalesOrders_Customers.GetCustomerRef(so).Load()
  End If
  Dim Cust As Customer
  Cust = FK_SalesOrders_Customers.GetCustomer(so)
  If Cust IsNot Nothing Then
    dgvList.Rows(intRow).Cells("CustomerID").Value = Cust.CustomerID
  End If
  Cust = Nothing
End Sub
If you execute the preceding code within a For...Next loop to retrieve the SalesOrder (so) entities, you must enable SQL Server 2005's Multiple Active Resultsets (MARS) feature to open a second DataReader on the same database connection:
'Retreive foreign key values on multiple connections
For Each so In Orders
  GetCustomerIDForSalesOrder(so, intRow)
  GetEmployeeIDForSalesOrder(so, intRow)
  GetShipperIDForSalesOrder(so, intRow)
  intRow += 1
Next
The alternative, which provides a very slight performance gain, is to iterate the List of SalesOrder instances three times to retrieve the foreign key values:
'Retreive foreign key values sequentially
For Each so In lstOrders
  GetCustomerIDForSalesOrder(so, intRow)
  intRow += 1
Next
intRow = 0
For Each so In lstOrders
  GetEmployeeIDForSalesOrder(so, intRow)
  intRow += 1
Next
intRow = 0
For Each so In lstOrders
  GetShipperIDForSalesOrder(so, intRow)
  intRow += 1
Next

Here's the WinForm test harness's DataGridView displaying a few foreign key values in the last three columns:

Notice the relatively long time (80 seconds) required for the almost 2,500 T-SQL queries required to retrieve the three foreign key values for 830 SalesOrder entities. Once the related entities are loaded in memory, execution time decreases dramatically, as shown here:

Note: The design of the Employees table implements the adjacency technique for representing a hierarchy in a table of a relational database. Path and nested sets are alternative—but less performant—approaches. Anthony Bloesch's February 15, 2006 "Hierarchies (trees) in SQL Server 2005" post compares the three techniques and their performance in a 20,000-node implementation.

Cache Uniqueing Issues and Lost Values

EDM employes uniquing, the process by which Object/Relational Mapping (O/RM) tools maintain a single copy of each unique entity instance, such as a Customer, Order, or Product, regardless of how many times a query retrieves an instance. The test harness's 91 Customers placed 830 Orders, thus the (830 - 91) or 739 Customer instances retrieved from the database to obtain foreign-key value are duplicates. Similarly, one of nine employees receive credit for orders so 821 retrieved Employee instances are duplicates. Finally, there are three shipping companies, so 827 Shipper instances are duplicates. Adding counters for the Load method of Customer, Employee, Shipper, Categorie, and Supplier entity instances confirms the retrieval of duplicates. (These counters aren't don't appear in the test harness screen captures.)

Uniquing is implemented by an Identity Map. Martin Fowler states in Patterns of Application Architecture that an Identity Map: "Ensures that each object gets loaded only once by keeping every loaded object in a map. Looks up objects using the map when referring to them." Most O/RMs implement Identity Maps in cache, often as a hashtable of values calculated from primary keys. The fact that the missing ReportsTo values are duplicates of the two values returned from the cache indicates a problem with the uniqueing algorithm.

Note: A counter on Employee entity instance retrievals indicates that Employee instances aren't cached. The first time cached Order instances are traversed, the Employee retrieval instance counter increments by 839; additional traversals increment by 830.

Frans Bouma, developer of the LLBGen O/RM for .NET and Microsoft MVP, contends in his "Why a cache in an O/R mapper doesn't make it fetch data faster" blog post that caching doesn't necessarily make data retrieval more efficient. The time to look up the newly retreived object's ID in an Indentity Map that contains a large number of hashes might contribute to the apparent poor performance when initially filling the Orders grid.

Composite Keys, Surrogate Keys, Natural Keys, and Ruby on Rails

Bouma also observes that "As ... compound [composite] PKs can complicate the calculation process, it's not that straight forward to get the lookup process of entities very efficient."

Ruby on Rails' lack of of composite PK support by its O/RM tool caused Martin Fowler to raise the spectre of substituting an autoincrementing (identity) integer column as a surrogate primary key. Jonathan Ellis' July 12, 2006 "Single column primary keys should be enough for anybody" post and Josh Berkus' three-part series on surrogate vs. "Primary Keyvil, Part I," "Part II (Reasons to Use an Autonumber Surrogate Key)," and "Part III (Reasons to Use an Autonumber Surrogate Key, Evaluated)" make the case for natural keys.

Note: Kevin Hoffman, TheDotNetAddict of .Net Developer's Journal, posted on October 6, 2006, "ASP.NET vs Ruby on Rails : Round 3 (Object-Relational Modeling)," which compares ASP.NET vNext's Entity Framework with Rails' ActiveRecord as an O/R Modeling approach. This page links to other Kevin Hoffman posts, many of which relate to LINQ, ASP.NET vNext, and ADOEF. Microsoft's Blinq tool, which has capabilities similar to Rails' scaffolding feature, handles composite keys with no problem. Blinq 1.0 uses LINQ to SQL (DLinq), not ADOEF.

Natural keys, which are values in the table, prevent entering duplicate data. The Northwind Order Details table has a composite natural primary key that consists of the OrderID and ProductID columns. In addition to uniquely identifying a row, the primary key prevents data entry operators from entering rows that duplicate a product line item in an order. Hopefully, support for composite primary keys will arrive in ADO.NET vNext shortly.

For general background on caching, read "Caching Architecture Guide for .NET Framework Applications," by Avi Ben-Menahem and Ronen Ashkenazi (patterns & practices).

Franz Brouma's "Essay: The Database Model is the Domain Model" offers an approachable view of the the major issues that O/RM seeks to address.

A related "Objectify Data With ADO.NET vNext" article in the October 2006 issue of Visual Studio Magazine provides more information about EF, EDM, and the EDM Designer.

Updated: 10/8/2006, 10/11/2006, 10/30/2006

Technorati Tags: ADO.NET vNext, Entity Framework, Entity Data Model, Entity Data Model Designer, EDM Designer, LINQ, LINQ to Entities, LINQ to SQL, Entity SQL, eSQL, DLinq, VB 9.0, Orcas

Saturday, September 16, 2006

Michael Arrington Badmouths Squidoo (Again)

Michael Arrington delivered a presentation to The Future of Web Apps conference held in San Francisco on September 13-14, 2006. According to Dan Farber, who covered the conference for ZD Net, Arrington included Squidoo in a "What were they thinking?" list of companies that he was "not proud that they exist."

The startups subject to Arrington's stigmata are Inform, Gather, PubSub, Browzor, Jigsaw, and Squidoo. Of that group, I'm only familiar with Squidoo and Gather; the preceding two links point to one of my Squidoo lenses and a Gather demonstration page.

Note: This post is an expansion of the "Subsequent Events [9/14-15/2006]" section of my August 6, 2006 "Hubpages' Attempt to Clone Squidoo is a Bust" post. This post was updated 9/18/2006.

Squidoo describes itself as "a new online platform and community that makes it easy for anyone to build a single page--called a lens--on a topic, idea, product or cause he is passionate about. These lenses in turn help finders get unique, human perspectives instead of computer-selected and often irrelevant search results."

Squidoo received favorable coverage in an April 10, 2006 New York Times article, "A Home Where Bloggers Can Plumb Those Obscure Passions." A Google search on "The Black Scholar" returns about 30,000 hits; my Squidoo lens on the topic is in second place—immediately after The Black Scholar's Web site.

Gather is a social sitebuilding startup that claims to be "a place to connect over common interests and passions, to engage in dialog or share different viewpoints." BusinessWeek's Liz Ryan named Gather one of the Top Ten Desktop Diversions of 2006 on March 27, 2006. I'm inclined to give a BusinessWeek columnist far more credence than a blog entrepreneur.

Arrington's Praise for Squidoo-Like Wiki Hosts

On June 18, 2006, Arrington favorably reviewed Wetpaint, an ad-supported Wiki hosting site, which received $5 million funding from Trinity Ventures and Frazier Technology Ventures. Arrington said that Wetpaint "is the best hosted wiki I’ve seen so far," comparing it to competitiors PBwiki, Wikia, and JotSpot.

Note: The "best hosted wiki I've seen so far" is StikiPad, based on my first tests of the preceding and a few other hosted wiki sites. StikiPad offers exceptional editing flexibility, doesn't clutter free accounts with AdSense adverts, and has a very intuitive and attractive UI. Here's a link to the default page for my first StikiPad wiki. Click here for a WikiMatrix comparison of JotSpot, PBWiki, Socialtext, StikiPad, and Wetpaint. StikiPad offers free as well as paid—$4.95, $9.95, and $14.95—accounts. (StikiPad is based on the Ruby-based Instiki wiki clone and the Ruby on Rails framework.)

My impression of these wiki sites is that they are simply free (ad-supported) or paid Web site hosts with multi-person editing, comments, or both enabled. For example, PBwiki offers free, $9.95, $24.95, and $34.95 per month options. JotSpot (requires free registration to read) has $9.95, $24.95, $69.95, and $199.95 per month plans. Wikia requires a wiki to "have a large potential audience and be likely to attract enough editors to maintain the wiki." The preceding links open simple test wikis; here's a link to a more complete Wetpaint wiki.

Note: No hosted wiki that I've seen so far, including Socialtext and wiki.com, has features that come close to matching the capabilities of Microsoft's Windows SharePoint Services (WSS) 2.0 or 3.0, which is a free add-in to Windows Server 2003 SP1. Stay tuned for a future post comparing WSS 3.0 and online wiki applications.

Wiki sites enable multi-person page editing, but most wiki sites offer far fewer editing widgets than Squidoo. I've seen nothing so far to convince me that any of these startups have much—if anything—more to offer than Squidoo, Google Pages, or Blogger. For example, Blogger lets you enable team blogging. If you're willing to take the risk, you can enable multi-person editing of Squidoo lenses by disclosing your username and password to trusted colleagues. Alternatively, you can set preferences to Share My Squidoo and enable anyone to edit your lens.

Rick Segal's Take on Arrington's Squidoo Castigation

Canadian venture capitalist Rick Segal takes on Arrington's castigation of Squidoo in a trilogy of posts—Mike Arrington - Sit Down, Michael Arrington Responds, and The Good of Web 2.0. Squidoo donates a portion of advertising revenue after operating expenses to charity, and Squidoo Lensmasters have the option of donating their Ad Sense earnings to charity.

One of Segal's issues is Arrington's insistence on an accounting of Squidoo's donations before considering a retraction of his miscategorization of Squidoo. According to Squidoo's Report page's Squidoo-wide Stats section, Total Money for Charity was $7,194.03 from 40,282 Total Lenses as of 9/19/2006.

Note: Here's how Squidoo distributes its income: "We divide up the money we receive in a very public way. First, we pay our bills. That's direct out of pocket expenses like rent and servers and salary and benefits expenses (our CEO doesn't take a salary, and neither does our board of directors). Then, with no other deductions, we pay 5% of our post-expense revenue directly to the charity pool, 50% directly to our lensmasters and retain the rest to pay off investors and employees." (From Everything about getting paid, "11. Does Squidoo Make a Profit?")

The fact that charities and Lensmasters are receiving payments—regardless of the amount—indicates that Squidoo is profitable and debunks Arrington's May 9, 2006 assertion that Squidoo is Seth Godin's "Purple Albatross." It's a good bet that Hubpages—a Squidoo rip-off and Arrington's favored topical Web page host—won't reach profitability before it burns through the $2 million funding it received earlier this year from Hummer-Winblad Venture Partners.

Arrington's Squidoo-related posts and comments demonstrate to me that he harbors personal enmity for Squidoo and/or Seth Godin. The question for TechCrunch readers is the extent to which this animus biases Arrington's "Web 2.0" reviews.

Technorati tags: , , , , , , , , ,