/// <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)); }
/// <summary> /// Construct an instance of the given type using data from the first row of the /// supplied SqlResult instance. /// Refer to the Construct method of the <see cref="ObjectMap"/> class for details. /// </summary> /// <param name="type">The type of object to construct</param> /// <param name="sr">The SqlResult instance holding the data</param> /// <param name="key">Additional fields not available in the result set (e.g. primary key fields)</param> /// <returns>An instance of the given type</returns> /// <exception cref="GentleException"> will be raised if no object could be created</exception> public static object GetInstance(Type type, SqlResult sr, Key key) { Check.Verify(sr != null && sr.ErrorCode == 0 && sr.RowsContained == 1, Error.UnexpectedRowCount, sr.RowsContained, 1); ObjectMap objectMap = GetMap(sr.SessionBroker, type); // check for dynamic type if (objectMap.InheritanceMap != null) { string assemblyQualifiedName = sr.GetString(0, objectMap.InheritanceMap.ColumnName); type = LoadType(assemblyQualifiedName); objectMap = GetMap(sr.SessionBroker, type); // update objectmap to actual type from database } // determine constructor object[] row = (object[])sr.Rows[0]; int columnComboHashCode = objectMap.DetermineConstructor(sr.ColumnNames, row); // create object object result = objectMap.Construct(columnComboHashCode, row, sr.SessionBroker); // check whether to store query result information if (GentleSettings.CacheObjects && GentleSettings.SkipQueryExecution && objectMap.CacheStrategy != CacheStrategy.Never) { IList <string> results = new List <string> { objectMap.GetInstanceHashKey(result) }; CacheManager.Insert(sr.Statement.CacheKey, results); } // mark as persisted if (result is IEntity) { (result as IEntity).IsPersisted = true; } return(result); }
/// <summary> /// Construct multiple objects of a given type from the data contained in the given SqlResult /// object. Refer to the Construct method of the <see cref="ObjectMap"/> class for details. /// </summary> /// <param name="type">The type of object to construct</param> /// <param name="sr">The SqlResult instance holding the data</param> /// <param name="result">An optional existing container in which to store the created objects. If /// this parameter is null a new IList instance will be created.</param> /// <returns>An IList holding the created objects</returns> /// <exception cref="GentleException"> will be raised if no object could be created</exception> public static IList GetCollection(Type type, SqlResult sr, IList result) { if (result == null) { result = MakeGenericList(type); } ObjectMap objectMap = GetMap(sr.SessionBroker, type); // check whether to store query result information bool isCache = GentleSettings.CacheObjects && GentleSettings.SkipQueryExecution && objectMap.CacheStrategy != CacheStrategy.Never; IList cache = isCache ? new ArrayList() : null; // remember keys of cached objects to permit SQE // process result set if (sr.RowsContained > 0) { ObjectMap actualMap = objectMap; int columnComboHashCode = 0; // cache constructor info for dynamic type construction Hashtable typeHash = null; Hashtable typeMaps = null; if (objectMap.InheritanceMap != null) { typeHash = new Hashtable(); typeMaps = new Hashtable(); } else // precompute fixed hash { columnComboHashCode = objectMap.DetermineConstructor(sr.ColumnNames, (object[])sr.Rows[0]); } // process result set for (int i = 0; i < sr.Rows.Count; i++) { object[] row = (object[])sr.Rows[i]; // dynamic object construction handling if (typeHash != null) { string assemblyQualifiedName = sr.GetString(i, objectMap.InheritanceMap.ColumnName); if (typeHash.ContainsKey(assemblyQualifiedName)) { columnComboHashCode = (int)typeHash[assemblyQualifiedName]; actualMap = (ObjectMap)typeMaps[assemblyQualifiedName]; } else { Type rowType = LoadType(assemblyQualifiedName); actualMap = GetMap(sr.SessionBroker, rowType); columnComboHashCode = actualMap.DetermineConstructor(sr.ColumnNames, (object[])sr.Rows[0]); typeMaps[assemblyQualifiedName] = actualMap; typeHash[assemblyQualifiedName] = columnComboHashCode; } } // skip non-derived classes for dynamic types if (actualMap.Type == objectMap.Type || actualMap.Type.IsSubclassOf(objectMap.Type)) { object obj = actualMap.Construct(columnComboHashCode, row, sr.SessionBroker); if (obj is IEntity) { (obj as IEntity).IsPersisted = true; } result.Add(obj); // cache result if necessary if (isCache) { cache.Add(actualMap.GetInstanceHashKey(obj)); } } } } if (isCache) { CacheManager.Insert(sr.Statement.CacheKey, cache); } return(result); }