Ejemplo n.º 1
0
        /// <summary>
        /// Add an object to the list. The object is created using values from the list of related
        /// objects passed. This means you dont pass the relation object itself, but rather the
        /// list of objects which are related (in an n:m fashion).
        /// </summary>
        /// <param name="transaction">The transaction within which to execute statements.</param>
        /// <param name="relatedObjects">The list of related objects</param>
        /// <returns>The index of the newly created relation</returns>
        public virtual int Add(Transaction transaction, params object[] relatedObjects)
        {
            Check.VerifyNotNull(relatedObjects, Error.NullParameter, "relatedObjects");
            int expectedArgs = parent == null ? 1 : 0;

            expectedArgs += relatedTypes.Length;
            Check.VerifyEquals(expectedArgs, relatedObjects.Length, Error.DeveloperError,
                               "Invalid use of GentleList (arguments to Add does not match managed type count).");
            Key key = new Key(containedMap.Type, true);

            key = Key.GetKey(broker, key, true, parent);
            // only add first object at this point
            key = Key.GetKey(broker, key, true, relatedObjects[0]);
            // check to see if relation exists based on first object alone
            object relation = relations.Find(key);

            if (relation != null)
            {
                return(relations.IndexOf(relation));
            }
            // make sure the relation is constructed using all objects passed
            for (int i = 1; i < relatedObjects.Length; i++)
            {
                key = Key.GetKey(broker, key, true, relatedObjects[i]);
            }
            relation = containedMap.Construct(key, broker);
            return(relations.Add(transaction, relation));
        }
Ejemplo n.º 2
0
        public object Via(int index)
        {
            if (listType != GentleListType.ManyToMany)
            {
                return(null);
            }
            Key key = new Key(viaMap.Type, true);

            key = Key.GetKey(broker, key, true, parent);
            key = Key.GetKey(broker, key, true, this[index]);
            return(broker.RetrieveInstance(viaMap.Type, key));
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Retrieve a list of objects of the given type constrained by the properties of
 /// this object instance.
 /// </summary>
 /// <param name="type">The type of objects being retrieved</param>
 /// <param name="propertyNames">A list of property names on the current object</param>
 /// <returns>A collection of objects of the given type</returns>
 protected virtual IList RetrieveList(Type type, params string[] propertyNames)
 {
     if (GetType().Equals(type))
     {
         // if the list type we're selecting is same type as self no foreign key
         // translation is required - simply use the name given
         return(broker.RetrieveList(type, Key.GetKey(broker, true, this, propertyNames)));
     }
     else
     {
         // get the key with values from current object
         Key key = Key.GetKey(broker, true, this, propertyNames);
         return(broker.RetrieveList(type, key));
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Search the list of contained objects for an entry whose key matches the given key. The
 /// first match is returned or null if no match was found.
 /// </summary>
 /// <param name="key">The key identifying the object to retrieve.</param>
 /// <returns>The first object matching the key.</returns>
 public virtual object Find(Key key)
 {
     if (Count > 0)
     {
         foreach (object obj in this)
         {
             Key objKey = Key.GetKey(broker, key.isPropertyKeys, obj);
             if (objKey.Equals(key))
             {
                 return(obj);
             }
         }
     }
     return(null);
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Add an object to the list. For 1:n relations, any references on the object being added
        /// to the parent of the list will be updated to match the parents current values, and the
        /// object will be inserted if it is a new one. For n:m relations, a new relation object is
        /// created and inserted (the object itself is never persisted).
        /// </summary>
        /// <param name="transaction">The transaction within which to execute statements.</param>
        /// <param name="value">The object to add to the list</param>
        /// <param name="relatedObjects">A list of values to use when creating the n:m relation
        /// object.</param>
        /// <returns>The index of the newly added object</returns>
        public virtual int Add(Transaction transaction, object value, params object[] relatedObjects)
        {
            Check.VerifyNotNull(value, Error.NullParameter, "value");
            Check.Verify(containedMap.Type.Equals(value.GetType()) ||
                         value.GetType().IsSubclassOf(containedMap.Type),
                         Error.UnsupportedType, value.GetType());
            // skip adding objects matching existing data
            object val = Find(Key.GetKey(broker, true, value));

            value = val ?? value;
            // manage 1:n relation
            if (viaInstances == null)
            {
                Check.Verify(relatedObjects == null || relatedObjects.Length == 0,
                             Error.NotImplemented, "Request incompatible with GentleList in OneToMany mode.");
                // manage added object
                IPersistent obj = value as IPersistent;
                if (!obj.IsPersisted)
                {
                    // first we update the foreign key property on the added object
                    UpdateForeignKeyFields(value);
                    if (transaction != null)
                    {
                        transaction.Persist(obj);
                    }
                    else
                    {
                        obj.Persist();
                    }
                }
            }
            else
            {
                // manage n:m relation object - creates new relation object using parent and value
                object[] args = Merge(value, relatedObjects);
                viaInstances.Add(transaction, args);
            }
            // this bit ensures object uniqing by disallowing objects with identical PK
            // from being in the list more than once
            if (val == null)
            {
                return(base.Add(value));
            }
            else
            {
                return(IndexOf(val));
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Removes a relation from the list. The relation to remove is found using values from the
        /// list of related objects passed. This means you dont pass the relation object itself, but
        /// rather the list of objects which are related (in an n:m fashion).
        /// </summary>
        /// <param name="transaction">The transaction within which to execute statements.</param>
        /// <param name="relatedObjects">The list of related objects</param>
        public virtual void Remove(Transaction transaction, params object[] relatedObjects)
        {
            Check.VerifyNotNull(relatedObjects, Error.NullParameter, "relatedObjects");
            Check.Verify(relatedObjects.Length > 0, Error.EmptyListParameter, "relatedObjects");

            /*Check.Verify( parent == null && relatedTypes.Length == 2 ||
             *      parent != null && relatedTypes.Length == 1, Error.NotImplemented,
             *            "The GentleRelation class is currently only able to manage two-way relations." );*/
            Key key = new Key(containedMap.Type, true);

            key = Key.GetKey(broker, key, true, parent);
            // only add first object at this point
            key = Key.GetKey(broker, key, true, relatedObjects[0]);
            // do not use additional relation objects when removing
            object relation = relations.Find(key);

            if (relation != null)
            {
                relations.Remove(transaction, relation);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Remove an object from the list. For 1:n relations, if the object is persisted it will also
        /// be removed from the database. For n:m relations, the relation object is removed (the object
        /// being removed is left untouched and must manually be removed if so desired).
        /// </summary>
        /// <param name="transaction">The transaction within which to execute statements.</param>
        /// <param name="value">The object to remove from the list</param>
        public virtual void Remove(Transaction transaction, object value)
        {
            object val = Find(Key.GetKey(broker, false, value));

            value = val ?? value;
            if (Contains(value))
            {
                Check.VerifyNotNull(value, Error.NullParameter, "value");
                Check.Verify(containedMap.Type.Equals(value.GetType()) ||
                             value.GetType().IsSubclassOf(containedMap.Type),
                             Error.UnsupportedType, value.GetType());
                // call remove even if contains was false to make sure error reporting is unchanged
                // Note: calling ArrayList/base class RemoveAt seems to work but calling Remove does
                // not - calling base.Remove ends up here again - must be a bug in net-1.1.
                base.RemoveAt(IndexOf(value));
                if (viaInstances == null)
                {
                    // manage removed object
                    IPersistent obj = value as IPersistent;
                    if (obj.IsPersisted)
                    {
                        if (transaction != null)
                        {
                            transaction.Remove(obj);
                        }
                        else
                        {
                            obj.Remove();
                        }
                    }
                }
                else
                {
                    // manage n:m relation object
                    viaInstances.Remove(transaction, value);
                }
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Abstract method for subclasses to implement. It should return a <see cref="Key"/>
 /// instance containing all the primary key properties of this object.
 /// </summary>
 /// <returns></returns>
 public virtual Key GetKey()
 {
     // the Key class knows how to build a key using reflection
     return(Key.GetKey(broker, true, this));
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Refresh the properties of the given object with the values from the
 /// database. This is essentially a Retrieve operation, but instead of
 /// returning a new object, the existing is updated. This allows it to be
 /// used within constructors.
 /// Throws an exception for unsupported types.
 /// </summary>
 /// <param name="obj">The object instance to update</param>
 public void Refresh(object obj)
 {
     Retrieve(obj, Key.GetKey(this, true, obj), null, null);
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Refresh the properties of the given object with the values from the
 /// database. This is essentially a Retrieve operation, but instead of
 /// returning a new object, the existing is updated. This allows it to be
 /// used within constructors.
 /// Throws an exception for unsupported types.
 /// </summary>
 /// <param name="obj">The object instance to update</param>
 /// <param name="tr">The database transaction for when participating in transactions.</param>
 public void Refresh(object obj, IDbTransaction tr)
 {
     Retrieve(obj, Key.GetKey(this, true, obj), tr.Connection, tr);
 }
Ejemplo n.º 11
0
 private SqlStatement GetStatement(object instance, StatementType stmtType)
 {
     return(GetStatement(instance.GetType(), Key.GetKey(this, true, instance), stmtType));
 }