/// <summary>
        /// Creates a new persisted object with the specified primary key.
        /// </summary>
        /// <param name="type">The type of object to create.</param>
        /// <param name="key">The user defined primary key</param>
        /// <remarks>
        /// This overload is for objects whose PrimaryKey is of type Identity or Guid (where ObjectServer handles primary key initialisation).
        /// If the primary key type is Defined then this overload will throw an exception.
        /// <para>
        /// The actual objects returned from a call to Create are not of the defined type but of a
        /// proxy class which sub-classes the persisted object and implements the abstract properties.
        /// This is transparent as long as no access to the type occurs. If this is done then it is
        /// nessecary to access the proxy's base type to get back to the defined type.
        /// </para>
        /// </remarks>
        /// <returns>A newly initialised proxy for the specified type.</returns>
        public ServerObject Create(Type type, object key)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type", "type cannot be null.");
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Creating new ServerObject of type " + type.FullName);

            TypeSchema schema = SchemaCache.Current.GetSchema(type);

            ServerObject obj = Activator.CreateInstance(schema.Proxy) as ServerObject;

            switch (schema.KeyType)
            {
            case PrimaryKeyType.Defined:
                if (key == null)
                {
                    throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "{0} KeyType is PrimaryKey.Defined and no has been key passed to ObjectTransaction.Create", type.FullName));
                }
                Trace.WriteLineIf(DebugOutput.Enabled, "Setting key to " + key);
                obj.Data.SetValue(schema.PrimaryKey.Property.Name, key);
                break;

            case PrimaryKeyType.Guid:
                Guid guid = Guid.NewGuid();
                Trace.WriteLineIf(DebugOutput.Enabled, "Setting key to " + guid);
                obj.Data.SetValue(schema.PrimaryKey.Property.Name, guid);
                break;

            case PrimaryKeyType.Identity:
                Trace.WriteLineIf(DebugOutput.Enabled, "Setting key to " + identityKey);
                obj.Data.SetValue(schema.PrimaryKey.Property.Name, identityKey);
                identityKey--;
                break;

            default:
                throw new ObjectServerException("Invalid PrimaryKeyType found.");
            }
            ;

            foreach (PropertySchema property in schema.PropertySchemas)
            {
                if (property.CanBeNull)
                {
                    obj.Data.SetValue(property.Property.Name, property.NullValue);
                }
            }

            obj.State = ObjectState.Added;
            obj.SetTransaction(this);

            objectCache.Add(obj);

            obj.PromptEvent(EventType.Created);
            obj.PromptEvent(EventType.Initialised);

            return(obj);
        }
        /// <summary>
        /// Retrieves an object from the data source of the specified type with the specified primary key.
        /// </summary>
        /// <remarks>
        /// Selects a single object from the data source using the given key to locate the values. If no values exist in the data source then Select returns null.
        /// <para>
        /// The actual objects returned from a call to Select are not of the defined type but of a
        /// proxy class which sub-classes the persisted object and implements the abstract properties.
        /// This is transparent as long as no access to the type occurs. If this is done then it is
        /// nessecary to access the proxy's base type to get back to the defined type.
        /// </para>
        /// </remarks>
        /// <param name="type">The type of object to create.</param>
        /// <param name="key">The primary key which to select the object in the data source.</param>
        /// <returns>A newly initialised proxy for the specified type and with the values given from the data source for the specified primary key.</returns>
        public ServerObject Select(Type type, object key)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type", "type cannot be null.");
            }

            if (key == null)
            {
                return(null);
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Selecting ServerObject of type " + type.FullName);

            ServerObject obj = objectCache.Get(type, key);

            if (obj != null)
            {
                return(obj);
            }

            try
            {
                adapter.Open();

                obj = adapter.Select(type, key);
            }
            finally
            {
                adapter.Close();
            }

            if (obj == null)
            {
                Trace.WriteLineIf(DebugOutput.Enabled, "No object found returning null");
                return(null);
            }

            obj.State = ObjectState.Unchanged;
            obj.SetTransaction(this);

            objectCache.Add(obj);

            obj.PromptEvent(EventType.Initialised);

            return(obj);
        }