Angelos Petropoulos' WebLog

Thoughts occasionally worth reading

(Interfaces && DI == Design.Good) does not always return true

clock April 30, 2008 09:38 by author angelosp

I have previously stated my reservations regarding Extensions methods, however this Eli Lopian's post still makes a good read.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


WinXP SP3 available in MSDN

clock April 24, 2008 13:24 by author angelosp

Those of you who have an MSDN subscription should be able to get WinXP SP3 by navigating to the "Top Subscriber Downloads" part of the MSDN home page (scroll at the bottom).

The link is labelled Windows XP Service Pack 3 (x86) - CD (English)

Update: It's worth noting that if for some reason you don't want Windows Update to install WinXP SP3 automatically, you can block it.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


A more straightforward Microsoft Unity quickstart

clock April 22, 2008 14:54 by author angelosp

I recently downloaded and started playing with Unity, trying to see if it fits our project's needs. You can grab the installer from CodePlex, which also includes a couple of quickstarts.

Personally I found the bundled quickstarts too advanced and complicated for someone that hasn't used IoC frameworks before. In my opinion they try to demonstrate too much functionality at once. In any case, I decided to create a small project that would put Unity to use and I thought I'd share it here, as others may find it useful.

Enjoy

Simple Unity Quickstart.zip (23.13 kb)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


ThreadPool - More threads per CPU, more memory consumed ... possible gotcha!

clock December 3, 2007 10:46 by author angelosp

So you know how the actual CLR hasn't changed since .NET 2.0? That is not entirely true (i.e. the one for Vista is a different build number), especially when you consider the .NET 3.5 release. The cut a long story short, Microsoft has taken the opportunity to include a service pack for the .NET CLR 2.0, which is a great thing as we are getting fixes for some annoying bugs.

One of the changes in SP1 of the CLR is the increase of the max number of threads per CPU that the .NET ThreadPool supports. It used to be 25 per CPU and the number has now increased to 250. Richard Blewett points out how this could be a potential gotcha as more threads means more memory consumed and ... well read the post! It's something not very likely to happen, but definitely worth knowing about. Plus, he talks about what brought this change, which is always interesting to know.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Using XML as a datatype in SQL Server 2005

clock November 28, 2007 22:14 by author angelosp

There are many articles and posts out there that describe the XML capabilities of SQL Server 2005. Some of the top links are

The Fundamentals of the SQL Server 2005 XML Datatype
XML Support in Microsoft SQL Server 2005
Introduction to XQuery in SQL Server 2005
Denis Ruckebusch's blog

The only problem is that you need to work rather hard to put all of this information together before you can get a decent working example. I went through this excercise myself, so I thought it would be worth posting it here. The example is simple, I want to store an XML in one of my columns and I want the XML to be typed (i.e. to adhere to a schema). The first step is to define the schema for the XML file and to import it into SQL Server 2005.

The schema defines the following structure

Order
    OrderItem
        Name
        Price
        Quantity 

Importing the schema into SQL server is pretty simple, just use following T-SQL statement

CREATE XML SCHEMA COLLECTION [dbo].[OrderCollection] AS
'<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Order">
    <xsd:complexType>
      <xsd:complexContent mixed="false">
        <xsd:restriction base="xsd:anyType">
          <xsd:sequence>
            <xsd:element minOccurs="0" maxOccurs="unbounded" name="OrderItem">
              <xsd:complexType>
                <xsd:complexContent mixed="false">
                  <xsd:restriction base="xsd:anyType">
                    <xsd:sequence minOccurs="0">
                      <xsd:element name="Name">
                        <xsd:complexType>
                          <xsd:simpleContent>
                            <xsd:extension base="xsd:string" />
                          </xsd:simpleContent>
                        </xsd:complexType>
                      </xsd:element>
                      <xsd:element name="Price">
                        <xsd:complexType>
                          <xsd:simpleContent>
                            <xsd:extension base="xsd:decimal" />
                          </xsd:simpleContent>
                        </xsd:complexType>
                      </xsd:element>
                      <xsd:element name="Quantity">
                        <xsd:complexType>
                          <xsd:simpleContent>
                            <xsd:extension base="xsd:integer" />
                          </xsd:simpleContent>
                        </xsd:complexType>
                      </xsd:element>
                    </xsd:sequence>
                  </xsd:restriction>
                </xsd:complexContent>
              </xsd:complexType>
            </xsd:element>
          </xsd:sequence>
        </xsd:restriction>
      </xsd:complexContent>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>'


Using SQL Server Management Studio you can confirm that the XML Schema is now available to be used by navigating to the "Types" node as shown below 


It is now possible to create a table and define one of its columns to be of the datatype XML and to ensure that the XML inserted into the column is validated against the schema we just added using the following T-SQL statement

CREATE TABLE [dbo].[Order](
    [ID] [bigint] IDENTITY(1,1) NOT NULL,
    [CustomerID] [bigint] NOT NULL,
    [Value] [xml](DOCUMENT [dbo].[OrderCollection]) NOT NULL
)


Inserting a record into the new table is still exactly the same as before, with the only difference now that one of the parameters will be an XML document

INSERT INTO [Order]
(
    [CustomerID],
    [Value]
)
VALUES
(
    1625,
    '<Order>
      <OrderItem>
        <Name>Chair</Name>
        <Price>12.99</Price>
        <Quantity>4</Quantity>
      </OrderItem>
      <OrderItem>
        <Name>Table</Name>
        <Price>44.99</Price>
        <Quantity>1</Quantity>
      </OrderItem>
    </Order>'

)


Now comes the interesting part. Of course you can now select this record within your application code and manipulate the XML using the standard libraries, but what if you want to access this information within SQL Server (perhaps through an ordinary stored procedure). Another possibility is that you would like to perform some reporting on the data that is stored within the XML document.

The following T-SQL will turn the XML file into tabular format, with columns for each element that contains a value (i.e. the elements  "Name", "Price" and "Quantity") and a new row for each instance of the element "OrderItem".

-- Declare a variable of type XML
DECLARE @xml XML
 
-- Assign the value of the XML document
-- we want to manipulate to the variable @xml
SELECT
    @xml = [Value]
FROM
    [Order]
WHERE
    ID = 1
 
-- Present the data in tabular format
SELECT
    -- Select the element "Name" and convert its value to a VARCHAR(100)
    OrderItemFragment.Details.query('Name').value('.', 'VARCHAR(100)') AS [Name],
    -- Select the element "Price" and conver its value to DECIMAL(28,2)
    OrderItemFragment.Details.query('Price').value('.', 'DECIMAL(28,2)') AS [Price],
    -- Select the element "Quantity" and convert its value to INTEGER
    OrderItemFragment.Details.query('Quantity').value('.', 'INTEGER') AS [Quantity]
FROM
    -- Split the XML document into individual pieces, one for each
    -- instance of the element "OrderItemFragment". Name the tabular result
    -- "OrderItem" and give its single column the name "Details"
    @xml.nodes('/Order/OrderItem') AS OrderItemFragment([Details])


The code is not really that complicated, but there are some rules.

  1. The function ".nodes()" used to split the XML file into fragments cannot be performed on value of the datatype XML. The reason I am selecting the XML file that I want to manipulate into a local variable first is to work around this limitation. I tried long and hard, but I could not get "Order.Value.nodes()" to work. (see "Update 29/11/2007")
  2. The output of the function ".nodes()" is tabular and has to be named and its columns have to be specified.
  3. The output of the function ".nodes()" can only be accessed through SQL XML functions such as ".value()", ".query()", ".count()", etc.


The line "@xml.nodes('/Order/OrderItem')" navigates through the XML document by first finding the element "Order" and then the element "OrderItem". Every time it comes across this relationship of elements (i.e. "Order" is parent and "OrderItem" is child) it seperate it from the rest of the document and returns an XML fragment that is the contents of the "OrderItem" element it has identified. The result of the XQuery statement is the collection of these XML fragments.

The line "OrderItemFragment.Details.query('Name').value('.', 'VARCHAR(100)') AS [Name]" uses the ".query()" function to find the element called "Name". It then uses the function ".value()" to retrieve the identified element's value and convert it to a SQL datatype.

The result are exactly what you would expect a T-SQL statement to return 

Update 29/11/2007: There had to be a way and sure enough I found it. You can use the ".nodes()" function on an XML columns straight in the "FROM" part of the statement rather than having to user a variable. The previous SQL statement is equivalent to this one

SELECT
    OrderItemFragment.Details.query('Name').value('.', 'VARCHAR(100)') AS [Name],
    OrderItemFragment.Details.query('Price').value('.', 'DECIMAL(28,2)') AS [Price],
    OrderItemFragment.Details.query('Quantity').value('.', 'INTEGER') AS [Quantity]
FROM
    [Order] CROSS APPLY [Value].nodes('/Order/OrderItem') AS OrderItemFragment([Details])
WHERE
    ID = 1

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Subscribe

Syndicate
AddThis Feed Button
AddThis Social Bookmark Button

Search

Calendar

<<  August 2008  >>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

Archive

Tags

Categories


Blogroll

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Sign in