Ryan Dawson on Longhorn

The software we think, but do not write

March 2004 - Posts

  • ObjectSpaces

    Filed under:

     

    ObjectSpaces

     

    The ObjectSpace technology, coupled with basic XML querying will eradicate current methods for database manipulation as we know them.  At least, that is how I feel.  In both statements, the back-end database remains essentially the same.  It is a column and row relational storage device.  But, in the former statement, you talk to the back-end through CLR objects, and the latter statement, you talk to the back-end through XML-ish procedures, including XQuery (In short, you only communicate in XML standards).

     

    So, the interesting thing is that nothing has really changed except productivity and portability.  The reason that I think the ObjectSpace will take hold is because no one works with the SqlDataReader for fun.  They work with it because they must read data, when the fact stands that the query is the only valuable piece of data that needs to be passed to the server.  Secondly, object orientation was decided a good thing for a good reason.  Now, my original premise will be broken in the fact that people will use a DataSet, but the abstraction for persistence will be the same as with ObjectSpaces.  The only reason that I think people will still use the DataSet is because it is easier for the short term.  We have a whole infrastructure built around tables –DataGrid for one.  I think the DataGrid is an uninteresting control (Although, not the concept of a table).  If anyone has tried to customize the DataGrid, you know that you have run into problems, or it is the fact that getting data in and out of the DataGrid is tedious.  Why is this?  The answer is because we don’t work in tables, we work in objects.  I would much rather have a DataGrid built on objects than rows and columns.  So, as you will see, the infrastructure was built around tables for simplicity, and not for API penetrability.

     

    When working with any of the new technologies in v2.0, you must notice that there are many facilities that translate relational content into objectified content, and this applies to things other than ObjectSpaces.  In order for you to understand ObjectSpaces, it should be worthwhile to have a look at how these technologies are glued togther.  There are three pieces to the puzzle: A Relational part, an Object part, and a part that ties the object and the relational parts together.

     

     

              Relational Schema

     

    The relational schema is the cardboard on the database side.  In essence, its purpose is to enumerate the columns that we want to use.  In this sense, we now have a vocabulary to talk about when we want to use the database.  We have therefore limited the database to only the fields that we care about, and have abstracted a layer over the database.

     

    What does this file look like?  You can obviously imagine that it is an XML file, but here is a sample:

     

    <rsd:Database Name="Northwind" Owner="sa" xmlns:rsd="http://schemas.microsoft.com/data/2002/09/28/rsd">

      <r:Schema Name="dbo" xmlns:r="http://schemas.microsoft.com/data/2002/09/28/rsd">

        <rsd:Tables>

          <rsd:Table Name="Customers">

            <rsd:Columns>

              <rsd:Column Name="CustomerID" SqlType="nchar" Precision="5" />

              <rsd:Column Name="CompanyName" SqlType="nvarchar" Precision="40" />

              <rsd:Column AllowDbNull="true" Name="ContactName" SqlType="nvarchar" Precision="30" />

            </rsd:Columns>

            <rsd:Constraints>

              <rsd:PrimaryKey Name="PK_Customers">

                <rsd:ColumnRef Name="CustomerID" />

              </rsd:PrimaryKey>

            </rsd:Constraints>

          </rsd:Table>

        </rsd:Tables>

      </r:Schema>

    </rsd:Database>

     

    I will take the fact that this XML file is self explanatory.  If you are familiar with the traditional relational storage system, you will not have any problems; otherwise, I recommend you review some of the essentials.

     

    One thing to note is that this table is provided in the default SQL Server installation as the Northwind database.

     

     

              Object Schema

               

    The object schema is the cardboard on the object side.  It represents the CLR object.  I will also take the fact that the representation is self explanatory, and the simple fact is that I cannot point you in the correct direction if you were to inquire more about the structure.

     

    <osd:ExtendedObjectSchema Name="DataTypesOSD" xmlns:osd="http://schemas.microsoft.com/data/2002/09/20/persistenceschema">

      <osd:Classes>

        <osd:Class Name="Customer">

          <osd:Member Name="ID" Key="true" />

          <osd:Member Name="Company" />

          <osd:Member Name="Name" />

        </osd:Class>

      </osd:Classes>

    </osd:ExtendedObjectSchema>

     

    Along with this, we should also probably define the object in our code file.  As the database was provided for us, this requires minimal work.

     

    public class Customer

    {

                public string ID;

                public string Name;

                public string Company;

    }

     

     

    Mapping Schema

     

    Obviously, the last piece in the puzzle is the glue for the two cardboard pieces.  This is the most interesting part, in my opinion.

     

    <m:MappingSchema xmlns:m="http://schemas.microsoft.com/data/2002/09/28/mapping">

       <m:DataSources>

          <m:DataSource Name="NorthwindRSD" Type="SQL Server" Direction="Source">

             <m:Schema Location="RSD.XML" />

             <m:Variable Name="Customers" Select="Customers" />

          </m:DataSource>

          <m:DataSource Name="DataTypesOSD" Type="Object" Direction="Target">

             <m:Schema Location="OSD.XML" />

          </m:DataSource>

       </m:DataSources>

       <m:Mappings>

          <m:Map SourceVariable="Customers" TargetSelect="Customer">

             <m:FieldMap SourceField="CustomerID" TargetField="ID" />

             <m:FieldMap SourceField="CompanyName" TargetField="Company" />

             <m:FieldMap SourceField="ContactName" TargetField="Name" />

          </m:Map>

       </m:Mappings>

    </m:MappingSchema>

     

    In the DataSources section, we square away the details of the stores we will be referencing as the source and destination (target).  As to how the name for our relational schema became NorthwindRSD, I have no idea; my only assumption is that you must append RSD on the end of the table name.  As for DataTypesOSD, we clearly defined that as the name of our object schema.  Considering that I have named the relational schema to RSD.XML and the object schema to OSD.XML, all is well.

     

    The mappings section is where things start to get a little more interesting.  As you will notice, we can simply state the SourceField and TargetField and the mapping will happen automatically.  It is as simple as referencing the names and we get an object to work with.

     

     

     

    Using the ObjectSpace

     

    Some notes before we continue.

     

    1. ObjectSpaces is currently only supported on a SqlConnection, so you must therefore have SQL Server running.  This is not to say that ODBC will not be supported before it ships.

     

    1. It is interesting that persistence of an object to a database is so easy, but we must remember that database updates are still expensive.

     

    1. You must reference the System.Data.ObjectSpaces and System.Data.SqlXml assemblies and namespaces.

     

     

    First order of business is to create a connection to the database:

     

    SqlConnection connection = new SqlConnection("Data Source=localhost; Integrated Security=SSPI; Database=northwind");

     

    I will not go over the details of a connection string, but suffice it to say that on a default installation of SQL Server Yukon, this connection string works.

     

    Next, we create the ObjectSpace:

     

    ObjectSpace os = new ObjectSpace(@"..\..\map.xml", connection);

     

    Considering that I named the mapping schema above as map.xml, and it is located in the root of my VS project, all is well.  That would also mean that the relational and object schemas were also in the same root folder.

     

    ObjectReader reader = os.GetObjectReader(new ObjectQuery(typeof(Customer), "Company = 'Microsoft'", ""));

     

    foreach (Customer c in reader)

    {

          // Handle customer

          // ...

    }

     

    reader.Close();

     

    • We get an ObjectReader by calling GetObjectReader on the ObjectQuery.  We pass in an ObjectQuery.  The ObjectQuery is composed of the return type as an instance of System.Type, an OPath, and a span.  The OPath is the new object language that is also used by WinFS.  Details may be found here http://longhorn.msdn.microsoft.com/lhsdk/ndp/daconcreatingobjectqueries.aspx.  The span, as far as I know, is a way to specify related tables that are in the OPath.  Otherwise, the OPath query will not return the expected results since it will treat the table in the OPath as empty.  Otherwise, if specified in the span, it will retrieve that table data, too.
    • You can iterate through the results with the respectable type, in this case, Customer.
    • You must close the reader

     

     

    On the other hand, to create a new object, we would use the following code:

     

    Customer customer = new Customer();

    // Modify customer ...

    os.StartTracking(customer, InitialState.Inserted);

    // Modify customer ...

    os.PersistChanges(customer);

     

    In order to set the object up for persistence, we call StartTracking.  The first parameter is the object, and the second is the state of the object.  There are two choices: Inserted or Unchanged.  Inserted means that the object is totally new and will equivocate into an INSERT SQL statement.  On the other hand, Unchanged actually means that you can change the object, however, an UPDATE SQL statement will be used at persistence time instead of an INSERT statement.  PersistChanges is the actual call to make things happen.

     

     

    One more thing.  Although this may seems obvious, all technologies like this (including XQuery and the like) actually translate their instructions into SQL statements before they are passed to the database provider.

     

    Where Are We?

     

    An ObjectSpace is the facility that allows a programmer to circumvent type mapping from a database to an object.  This significantly increases productivity and programmability.  There are three schema files required to make this happen: an object schema, a relational schema, and the mapping schema that interoperates the two.  The main query mechanism in ObjectSpaces is an OPath statement.

     

    PostTypeIcon
    7,311 Views
  • ContactPickerDialog

    Filed under:

     

    A semi interesting UI control is the ContactPickerDialog:

     

     

    Longhorn is slated to have many standard UI controls like this that represent social aspects, like Contacts.

     

    Anyway, programming against the ContactPickerDialog is straight forward.

     

    ContactPickerDialog picker = new ContactPickerDialog();

     

    picker.Title = "Invite These People";

    picker.DefaultFolder = ContactPickerDialog.PersonalContacts;

    picker.Layout = ContactPickerDialogLayout.DisplayPropertiesAtBottom;

    picker.OkButtonLabel = "Invite";

    picker.MultiSelect = true;

     

    ContactPropertyRequest contact = new ContactPropertyRequest(ContactPropertyType.Contact);

                picker.PropertyRequests.Add(contact);

     

    ContactPropertyRequest email = new ContactPropertyRequest(ContactPropertyType.EmailAddress);

                      picker.PropertyRequests.Add(email);

     

    if (picker.ShowDialog(this) == DialogResult.OK)

    {

          foreach (ContactSelection item in picker.SelectedContacts)

          {

                // ...

          }

    }

     

     

    There are a couple of things to note:

     

    • You can customize the Contacts that are shown by default (PersonalContacts, CorporateDirectory) and some of the small things like the Title.
    • You can define the columns, per se, as in the ContactPropertyRequest objects.  This will also add a button to the bottom in case you only want to add that specific property, such as EmailAddress.  On the other hand, ContactPropertyType.Contact will give all of the contact details (not that they are all shown as columns, though).

     

    PostTypeIcon
    1,733 Views
  • Browse Together Article

    Filed under:

     

    This article will focus on the Real Time Communication stack that is present in Longhorn.  We will implement an instant messaging application that allows two users to browse the internet and chat together.  Further, an introduction to the managed web browser; and, hosting WinForms controls inside Avalon.

     

    The article can be found here

     

     

     

    PostTypeIcon
    1,802 Views