ObjectPersistence Toolkit

Nizar posted a message on the news:microsoft.public.objectspaces group with a question on the ObjectPersistence Toolkit. He got an Exception from System.Data.SqlXml with an error message when trying to persist an object from a class that’s essentially the same as this one:

namespace Console_persistence
{
  public class Person
  {
    public int id;
    public string name;
    public DateTime birthday;
  }
}

The message is “Validation error at 5, 8: Cannot locate a domain structure for ‘Console_persistence.Person’ “.

If you are unfamiliar with the ObjectPersistence Toolkit (download it here) here is what it does. It will generate all three schemas for use in ObjectSpaces for an set of classes and will create the corresponding database for you. This means that you can start with just objects/classes and let the rest be generated for you. For every type a table will be generated, and an autoincrement key is added to your object to guarantee a unique key.

When I looked into the problem I found that the three schema files and the database are created. Not correctly enough, because the namespace of the persistent class is indirectly used (amongst other things) in the names of the tables. It kinda works for a single namespace, but leads to the problem that Nizar was experiencing. For a nested namespace (e.g. MyCompany.MyFramework) you get a ArgumentException from System.Data.SqlXml that “Value does not fall within the expected range.”. Also the name of the relational schema is set to the namespace. This gives you two problems:

  1. The schema name is used to get to the the database object as in DATABASENAME.SCHEMANAME.TABLENAME. This should correspond to a partially qualified name for a SQL Server object DATABASE.OWNER.OBJECT.
    For a RSD file that looks like this:

    <rsd:Database Name=”ObjectPersistence” xmlns:rsd=”http://schemas.microsoft.com/data/2002/09/28/rsd“>
      <rsd:Schema Name=”MyCompany.MyFramework”>
        <rsd:Tables>
          <rsd:Table Name=”MyCompany.MyFramework.Person”>


    the db object would be ObjectPersistence.[MyCompany.MyFramework].[MyCompany.MyFramework.Person]
    That doesn’t work well as you might guess, especially as the owner is always dbo when the ObjectPersistence Toolkit creates the table. It would have been better if the schema name is dbo. There must be a reason why the schema name is set to the namespace, but I couldn’t figure it out.
  2. ObjectSpaces doesn’t handle tables and views with dots in them very well. You can check this by changing the schema name to dbo. The same problems as before occur.
Three ways to solve these problems (from my post in the newsgroup):
  1. Remove the namespace(s) from the classes.
  2. Let the application generate the schema files incorrectly. Then edit the rsd.xml file and change the Schema name to dbo at the second line like so:

    <rsd:Schema Name="dbo“><rsd:Database Name=”ObjectPersistence” xmlns:rsd=”http://schemas.microsoft.com/data/2002/09/28/rsd“>
      <rsd:Schema Name=”dbo“>
        <rsd:Tables>
          <rsd:Table Name=”MyCompany.MyFramework.Person”>

    Also, change the tablenames in the rsd.xml file to the simple type names, i.e. remove the namespaces. Then edit the msd file and change the Select
    attributes of the map:Variable nodes to include the same tablenames:

    <map:Variable Name=”Namespace.Person_Rows” Select=”Person” />
    <map:Variable Name="Namespace.Person_Rows" Select="Person“>

  3. Change the source code of the Toolkit project if you dare and recompile.
    You would have to change the following on the RsdClasses.cs file.

    WARNING: not tested for all circumstances and use at your own risk.

    Line 242:
    string schemaName = type.ClassTypeInfo.Namespace == null ? “dbo” :
    type.ClassTypeInfo.Namespace;

    change to:

    string schemaName = “dbo”;

    Line 247:
    RelationalSchemaTable rsdTable =
        rsdSchema.Tables.Add(type.Name);

    change to:

    string tableName = type.Name;
    int dotIndex = tableName.LastIndexOf(‘.’);
    if (dotIndex >= 0)
    tableName = tableName.Substring(dotIndex + 1);
    RelationalSchemaTable rsdTable =
        rsdSchema.Tables.Add(tableName);

    That got it all working for me.

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s