/// <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); } } }
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); }
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; } } }
internal ObjectData(ServerObject obj) { Trace.WriteLineIf(DebugOutput.Enabled, "Initialising ObjectData"); this.obj = obj; data = new Hashtable(); }
/// <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); } } }