/// <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);
        }
        private void CommitChildren(ServerObject obj, object key)
        {
            Trace.WriteLineIf(DebugOutput.Enabled, "Enumerating children");

            TypeSchema schema = SchemaCache.Current.GetSchema(obj.ServerObjectType);

            if (key != null)
            {
                foreach (ChildrenSchema childSchema in schema.ChildrenSchemas)
                {
                    ServerObjectCollection children = obj.Children.GetValue(childSchema.Property.Name);

                    if (children == null)
                    {
                        continue;
                    }

                    TypeSchema   childTypeSchema = SchemaCache.Current.GetSchema(childSchema.ChildType);
                    ParentSchema parentSchema    = childTypeSchema.FindParentSchema(childSchema.PropertyName);

                    foreach (ServerObject child in children)
                    {
                        if (child.Parents.GetValue(parentSchema.Property.Name) != obj)
                        {
                            continue;
                        }

                        child.Data.SetValue(parentSchema.Property.Name, key);
                    }
                }
            }

            foreach (ChildrenSchema childSchema in schema.ChildrenSchemas)
            {
                ServerObjectCollection children = obj.Children.GetValue(childSchema.Property.Name);

                if (children == null)
                {
                    continue;
                }

                foreach (ServerObject child in children)
                {
                    Commit(child, true);
                }
            }
        }
示例#3
0
        public ServerObject Add(ServerObject obj)
        {
            Type       type   = obj.ServerObjectType;
            TypeSchema schema = SchemaCache.Current.GetSchema(type);
            object     key    = obj.Data.GetValue(schema.PrimaryKey.Property.Name);

            Trace.WriteLineIf(DebugOutput.Enabled, "Adding object with key " + key.ToString());

            if (objectCache.ContainsKey(key))
            {
                Trace.WriteLineIf(DebugOutput.Enabled, "Object already in cache, returning orginal");
                return(objectCache[key] as ServerObject);
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Adding object to cache");

            objectCache.Add(key, obj);
            return(obj);
        }
        internal ServerObjectCollection SelectChildren(ServerObject obj, string propertyName)
        {
            Trace.WriteLineIf(DebugOutput.Enabled, "Selecting children for " + propertyName);

            TypeSchema     schema         = SchemaCache.Current.GetSchema(obj.ServerObjectType);
            ChildrenSchema childrenSchema = schema.FindChildrenSchema(propertyName);

            ServerObjectCollection children = null;

            object primaryKey = obj.Data.GetValue(schema.PrimaryKey.Property.Name);

            Query query = new Query(new Condition(childrenSchema.PropertyName, Expression.Equal, primaryKey));

            children = Select(childrenSchema.ChildType, query);

            Trace.WriteLineIf(DebugOutput.Enabled, "Checking cache for more items");

            foreach (ServerObject cacheItem in objectCache.GetCacheItem(childrenSchema.ChildType))
            {
                if (primaryKey.Equals(cacheItem.Data.GetValue(childrenSchema.PropertyName)) && !children.Contains(cacheItem))
                {
                    children.Add(cacheItem);
                }
            }

            ServerObjectCollection toRemove = new ServerObjectCollection();

            foreach (ServerObject child in children)
            {
                if (!primaryKey.Equals(child.Data.GetValue(childrenSchema.PropertyName)))
                {
                    toRemove.Add(child);
                }
            }

            foreach (ServerObject child in toRemove)
            {
                children.Remove(child);
            }

            return(children);
        }
示例#5
0
        public ServerObject Add(ServerObject obj)
        {
            Type type = obj.ServerObjectType;

            Trace.WriteLineIf(DebugOutput.Enabled, "Adding object of type " + type.FullName);

            if (typeCache.ContainsKey(type.FullName))
            {
                Trace.WriteLineIf(DebugOutput.Enabled, "CacheItem found");
                CacheItem CacheItem = typeCache[type.FullName] as CacheItem;
                return(CacheItem.Add(obj));
            }
            else
            {
                Trace.WriteLineIf(DebugOutput.Enabled, "Creating new CacheItem");
                CacheItem CacheItem = new CacheItem();
                typeCache.Add(type.FullName, CacheItem);
                return(CacheItem.Add(obj));
            }
        }
        /// <summary>
        /// Marks a object for removal in the transaction.
        /// </summary>
        /// <remarks>
        /// This method can take a lengthy time dependent on its position in the relational graph due to having to
        /// traverse an object's child objects and either delete or set to null.
        /// <para>
        /// If the object graph traversal encounters an child relation with at least one valid object and ActionOnDelete is
        /// <see cref="DeleteAction.Throw">DeleteAction.Throw</see> then an <see cref="ObjectServerException">ObjectServerException</see>
        /// will be thrown. It is likely that the object graph will be left in an invalid state and it is not advised to <see cref="ObjectTransaction.Commit">Commit</see>
        /// the transaction.
        /// </para>
        /// </remarks>
        /// <param name="obj">The object to be marked for removal.</param>
        public void Delete(ServerObject obj)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj", "obj cannot be null.");
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Deleting object of type " + obj.ServerObjectType);

            DeleteImpl(obj);

            Trace.WriteLineIf(DebugOutput.Enabled, "Clearing Processed Objects");

            foreach (CacheItem cacheItem in objectCache)
            {
                foreach (ServerObject item in cacheItem)
                {
                    item.Processed = false;
                }
            }
        }
示例#7
0
 internal ObjectData(ServerObject obj)
 {
     Trace.WriteLineIf(DebugOutput.Enabled, "Initialising ObjectData");
     this.obj = obj;
     data     = new Hashtable();
 }
示例#8
0
        /// <summary>
        /// Gets or sets the <see cref="ServerObject">ServerObject</see> that is a Parent object.
        /// </summary>
        /// <remarks>
        /// On object access if a parent exists but has not be retrieved by ObjectServer then it will be retrieved and returned.
        /// Otherwise the existing object will be returned. If you wish a null value to be set the assign null to the parent.
        /// When an object is assigned as a parent, ObjectServer will locate the correct children collection and automatically append the current object.
        /// </remarks>
        /// <param name="key">The name of the property in the <see cref="ServerObject">ServerObject</see> which exposes this Parent.</param>
        /// <value>A <see cref="ServerObject">ServerObject</see> that is a Parent object or if no parent exists null.</value>
        public ServerObject this[string key]
        {
            get
            {
                if (data[key] == null)
                {
                    Trace.WriteLineIf(DebugOutput.Enabled, "Parent not found, loading");

                    TypeSchema   schema       = SchemaCache.Current.GetSchema(obj.ServerObjectType);
                    ParentSchema parentSchema = schema.FindParentSchema(key);

                    ServerObject parent = obj.Transaction.Select(parentSchema.Property.PropertyType, obj.Data.GetValue(key));

                    data[key] = parent;
                    return(parent);
                }
                else if (Convert.IsDBNull(data[key]))
                {
                    Trace.WriteLineIf(DebugOutput.Enabled, "Key Value is DBNull.Value returning null");
                    return(null);
                }

                return(data[key] as ServerObject);
            }
            set
            {
                if (value == null)
                {
                    Trace.WriteLineIf(DebugOutput.Enabled, "Parent set to null, setting key value to DBNull.Value");

                    obj.Data.SetValue(key, DBNull.Value);
                    data[key] = DBNull.Value;

                    UpdateState(key);
                }
                else
                {
                    if (!value.Equals(data[key]))
                    {
                        Trace.WriteLineIf(DebugOutput.Enabled, "New Parent set");

                        ServerObject newParent = value as ServerObject;

                        ServerObject oldParent = data[key] != null ? data[key] as ServerObject : null;

                        TypeSchema schema    = SchemaCache.Current.GetSchema(newParent.ServerObjectType);
                        object     parentKey = newParent.Data.GetValue(schema.PrimaryKey.Property.Name);

                        obj.Data.SetValue(key, parentKey);

                        data[key] = newParent;
                        UpdateState(key);

                        foreach (ChildrenSchema childSchema in schema.ChildrenSchemas)
                        {
                            if (childSchema.PropertyName == key && childSchema.ChildType == obj.ServerObjectType)
                            {
                                if (oldParent != null)
                                {
                                    Trace.WriteLineIf(DebugOutput.Enabled, "Removing from children collection " + childSchema.Property.Name);
                                    ServerObjectCollection oldChildren = oldParent.Children.GetValue(childSchema.Property.Name);
                                    if (oldChildren != null && oldChildren.Contains(obj))
                                    {
                                        oldChildren.Remove(obj);
                                    }
                                }

                                Trace.WriteLineIf(DebugOutput.Enabled, "Adding to children collection " + childSchema.Property.Name);
                                ServerObjectCollection newChildren = newParent.Children.GetValue(childSchema.Property.Name);
                                if (newChildren != null && !newChildren.Contains(obj))
                                {
                                    newChildren.Add(obj);
                                }

                                break;
                            }
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Inserts the specified <see cref="ServerObject">ServerObject</see> into the collection at the specified index.
 /// </summary>
 /// <param name="index">The zero-based index where the specified object should be inserted.</param>
 /// <param name="obj">The <see cref="ServerObject">ServerObject</see> to insert. </param>
 public void Insert(int index, ServerObject obj)
 {
     List.Insert(index, obj);
 }
 /// <summary>
 /// Gets the index in the collection of the specified <see cref="ServerObject">ServerObject</see>, if it exists in the collection.
 /// </summary>
 /// <param name="obj">The <see cref="ServerObject">ServerObject</see> to locate in the collection.</param>
 /// <returns>The index in the collection of the specified object, if found; otherwise, -1.</returns>
 public int IndexOf(ServerObject obj)
 {
     return(List.IndexOf(obj));
 }
 /// <summary>
 /// Gets a value indicating whether the collection contains the specified <see cref="ServerObject">ServerObject</see>.
 /// </summary>
 /// <param name="obj">The <see cref="ServerObject">ServerObject</see> to search for in the collection. </param>
 /// <returns><see langword="true">true</see> if the collection contains the specified object; otherwise, <see langword="false">false</see>.</returns>
 public bool Contains(ServerObject obj)
 {
     return(List.Contains(obj));
 }
 /// <summary>
 /// Removes the specified <see cref="ServerObject">ServerObject</see> from the collection.
 /// </summary>
 /// <param name="obj">The <see cref="ServerObject">ServerObject</see> to remove from the collection.</param>
 /// <exception cref="ArgumentException">
 /// The specified object is not found in the collection.
 /// </exception>
 public void Remove(ServerObject obj)
 {
     List.Remove(obj);
 }
 /// <summary>
 /// Adds the specified <see cref="ServerObject">ServerObject</see> to the collection.
 /// </summary>
 /// <param name="obj">The <see cref="ServerObject">ServerObject</see> to add.</param>
 /// <returns>The index at which the new element was inserted.</returns>
 public int Add(ServerObject obj)
 {
     return(List.Add(obj));
 }
        internal bool Commit(ServerObject obj, bool ignoreVisited)
        {
            if (obj.Processed)
            {
                return(true);
            }

            if (obj.Visited && !ignoreVisited)
            {
                return(false);
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Commiting ServerObject of type " + obj.ServerObjectType);

            TypeSchema schema = SchemaCache.Current.GetSchema(obj.ServerObjectType);

            obj.Visited = true;

            switch (obj.State)
            {
            case ObjectState.Added:

                obj.PromptEvent(EventType.Validate);

                if (!CommitParents(obj))
                {
                    break;
                }

                if (!obj.Processed)
                {
                    Trace.WriteLineIf(DebugOutput.Enabled, "Inserting ServerObject of type " + obj.ServerObjectType);
                    adapter.Insert(obj);
                    obj.Processed = true;
                }

                CommitChildren(obj, obj.Data.GetValue(schema.PrimaryKey.Property.Name));

                obj.State = ObjectState.Unchanged;
                break;

            case ObjectState.Deleted:
                CommitChildren(obj, null);

                Trace.WriteLineIf(DebugOutput.Enabled, "Deleting ServerObject of type " + obj.ServerObjectType);

                obj.PromptEvent(EventType.Deleted);

                adapter.Delete(obj);
                obj.Processed = true;

                CommitParents(obj);

                obj.State = ObjectState.Detached;
                break;

            case ObjectState.Modified:

                obj.PromptEvent(EventType.Validate);

                if (!CommitParents(obj))
                {
                    break;
                }

                if (!obj.Processed)
                {
                    Trace.WriteLineIf(DebugOutput.Enabled, "Updating ServerObject of type " + obj.ServerObjectType);
                    adapter.Update(obj);
                    obj.Processed = true;
                }

                CommitChildren(obj, obj.Data.GetValue(schema.PrimaryKey.Property.Name));

                obj.State = ObjectState.Unchanged;
                break;

            case ObjectState.Unchanged:
            case ObjectState.Detached:

                obj.Processed = true;

                break;

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

            return(obj.Processed);
        }
        private void DeleteImpl(ServerObject obj)
        {
            if (obj.Processed)
            {
                return;
            }

            Trace.WriteLineIf(DebugOutput.Enabled, "Deleting ServerObject of type " + obj.ServerObjectType);

            switch (obj.State)
            {
            case ObjectState.Added:
                Trace.WriteLineIf(DebugOutput.Enabled, "Setting state to ObjectState.Detached");
                obj.State = ObjectState.Detached;
                break;

            case ObjectState.Modified:
            case ObjectState.Unchanged:
                Trace.WriteLineIf(DebugOutput.Enabled, "Setting state to ObjectState.Deleted");
                obj.State = ObjectState.Deleted;
                break;

            case ObjectState.Deleted:
            case ObjectState.Detached:
                break;

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

            obj.Processed = true;

            TypeSchema parentTypeSchema = SchemaCache.Current.GetSchema(obj.ServerObjectType);

            Trace.WriteLineIf(DebugOutput.Enabled, "Enumerating Childrean");

            foreach (ChildrenSchema childSchema in parentTypeSchema.ChildrenSchemas)
            {
                Trace.WriteLineIf(DebugOutput.Enabled, "Checking Children " + childSchema.Property.Name);

                ServerObjectCollection children = obj.Children[childSchema.Property.Name] as ServerObjectCollection;

                TypeSchema childTypeSchema = SchemaCache.Current.GetSchema(childSchema.ChildType);

                ParentSchema parentSchema = childTypeSchema.FindParentSchema(childSchema.PropertyName);

                int nonDeleted = 0;

                foreach (ServerObject child in children)
                {
                    if (child.State != ObjectState.Deleted && child.State != ObjectState.Detached)
                    {
                        nonDeleted++;
                    }
                }

                Trace.WriteLineIf(DebugOutput.Enabled, "Counted " + nonDeleted + " non-deleted children");

                if (nonDeleted > 0)
                {
                    if (parentSchema.DeleteAction == DeleteAction.Throw)
                    {
                        throw new ObjectServerException(String.Format(CultureInfo.CurrentCulture, "Could not delete, {0}.{1} has DeleteAction.Throw", childTypeSchema.Type.FullName, parentSchema.Property.Name));
                    }

                    if (parentSchema.DeleteAction == DeleteAction.Null)
                    {
                        Trace.WriteLineIf(DebugOutput.Enabled, "Changing key to DBNull.Value and updating state");

                        foreach (ServerObject child in children)
                        {
                            child.Data.SetValue(childSchema.PropertyName, DBNull.Value);

                            switch (child.State)
                            {
                            case ObjectState.Added:
                            case ObjectState.Modified:
                            case ObjectState.Detached:
                            case ObjectState.Deleted:
                                break;

                            case ObjectState.Unchanged:
                                child.State = ObjectState.Modified;
                                break;

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

                        continue;
                    }
                }

                Trace.WriteLineIf(DebugOutput.Enabled, "Processing children");

                foreach (ServerObject child in children)
                {
                    DeleteImpl(child);
                }
            }
        }