/// <summary> /// Obtain a <see cref="FieldMap"/> instance from the current map. The field /// must be a foreign key reference to the given property on the given type. /// </summary> /// <param name="referencedType">The type to which the property should refer</param> /// <param name="propertyName">The name of the property on the referenced type</param> /// <returns>The FieldMap of the foreign key property from this map</returns> public FieldMap GetForeignKeyFieldMap(Type referencedType, string propertyName) { ObjectMap referencedMap = ObjectFactory.GetMap(broker, referencedType); FieldMap fm = GetForeignKeyFieldMap(referencedMap.QuotedTableName, referencedMap.GetFieldMap(propertyName).QuotedColumnName); // If no relation was found, try the reverse // TODO this is only here because relation info is only stored with the map // having the foreign key column; it will be removed in the future if (fm == null) { foreach (FieldMap reverse in Fields) { fm = referencedMap.GetForeignKeyFieldMap(QuotedTableName, reverse.QuotedColumnName); if (fm != null && fm.MemberName == propertyName) { return(reverse); } else { fm = null; } } } Check.VerifyNotNull(fm, Error.DeveloperError, "The type {0} does not have a foreign key relation to the property {1} " + "of type {2}. Check if you need to add a ForeignKey attribute.", Type.Name, propertyName, referencedType); return(fm); }
/// <summary> /// Obtain a key for the specified object instance and property names. The returned /// key will contain the corresponding column names for the type, and thus foreign /// key columns must use identical naming for this to work. /// </summary> /// <param name="broker">The optional PersistenceBroker instance to use for obtaining the /// ObjectMap for the supplied object instance. If this parameter is null, Gentle will try /// to infer the broker from the object instance. If that fails, it will use the default /// provider.</param> /// <param name="key">An optional existing key to add the values to</param> /// <param name="isPropertyKeys">False is key indexers are column names, true for property names</param> /// <param name="instance">The object instance whose property values will be used</param> /// <param name="members">The names of the properties to include in the key</param> /// <returns>The key</returns> public static Key GetKey(PersistenceBroker broker, Key key, bool isPropertyKeys, object instance, params string[] members) { Check.VerifyNotNull(instance, Error.NullParameter, "instance"); // try to infer broker from instance if (broker == null && instance is IBrokerLock) { broker = (instance as IBrokerLock).SessionBroker; } // WARNING/TODO if broker is null here and no ObjectMap yet exists for the type, // the DefaultProvider will be used to create the ObjectMap ObjectMap map = ObjectFactory.GetMap(broker, instance); // only set source type reference if this is a new key if (key == null) { key = new Key(map.GetTableName(instance), instance.GetType(), isPropertyKeys); } //else // Check.Verify( ! key.isPropertyKeys, Error.DeveloperError, // "Unable to combine keys containing property names due to possible name clashes." ); Check.VerifyEquals(key.isPropertyKeys, isPropertyKeys, "Cannot combine property and " + "column names in a single key - use one or the other."); Check.VerifyNotNull(members, Error.NullParameter, "members"); // process the list of specified properties foreach (string memberName in members) { FieldMap fm = isPropertyKeys ? map.GetFieldMap(memberName) : map.GetFieldMapFromColumn(memberName); Check.VerifyNotNull(fm, Error.NoProperty, map.Type, memberName); // FIXME outdated error message object memberValue = fm.GetValue(instance); // translate foreign references to local names if (key.SourceType != map.Type) { // WARNING/TODO if broker is null here and no ObjectMap yet exists for the type, // the DefaultProvider will be used to create the ObjectMap ObjectMap keyMap = ObjectFactory.GetMap(broker, key.SourceType); fm = keyMap.GetForeignKeyFieldMap(map.TableName, fm.ColumnName); } key[isPropertyKeys ? fm.MemberName : fm.ColumnName] = memberValue; } // add concurrency value if enabled and instance has revision column if (GentleSettings.ConcurrencyControl && map.ConcurrencyMap != null) { long version = Convert.ToInt64(map.ConcurrencyMap.GetValue(instance)); key[isPropertyKeys ? map.ConcurrencyMap.MemberName : map.ConcurrencyMap.ColumnName] = version; } return(key); }
internal Key ResolveForeignKeyReferences(Type type, Key key) { // determine whether we need to translate names if (key.SourceType != null && key.SourceType != type) { // translate column names in key to foreign key name in table used by type Key fkKey = new Key(type, false); ObjectMap map = ObjectFactory.GetMap(this, key.SourceType); ObjectMap fkMap = ObjectFactory.GetMap(this, type); foreach (string name in key.Keys) { string fieldName = key.isPropertyKeys ? name : map.GetPropertyName(name); FieldMap fkfm = fkMap.GetForeignKeyFieldMap(map.Type, fieldName); fkKey[fkfm.ColumnName] = key[name]; } key = fkKey; } return(key); }