private String GetMappedBy(Mapping.Collection collectionValue) { PersistentClass referencedClass = ((OneToMany)collectionValue.Element).AssociatedClass; // If there's an @AuditMappedBy specified, returning it directly. String auditMappedBy = propertyAuditingData.AuditMappedBy; if (auditMappedBy != null) { return(auditMappedBy); } IEnumerator <Property> assocClassProps = referencedClass.PropertyIterator.GetEnumerator(); while (assocClassProps.MoveNext()) { Property property = assocClassProps.Current; if (Toolz.IteratorsContentEqual(property.Value.ColumnIterator.GetEnumerator(), collectionValue.Key.ColumnIterator.GetEnumerator())) { return(property.Name); } } throw new MappingException("Unable to read the mapped by attribute for " + propertyName + " in " + referencingEntityName + "!"); }
/// <summary> /// Ctor /// </summary> /// <param name="metaDataStore"></param> /// <param name="mainGenerator">Main generator, giving access to configuration and the basic mapper.</param> /// <param name="propertyValue">Value of the collection, as mapped by Hibernate.</param> /// <param name="currentMapper">Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper} will be added.</param> /// <param name="referencingEntityName">Name of the entity that owns this collection.</param> /// <param name="xmlMappingData">In case this collection requires a middle table, additional mapping documents will be created using this object.</param> /// <param name="propertyAuditingData"> /// Property auditing (meta-)data. Among other things, holds the name of the /// property that references the collection in the referencing entity, the user data for middle (join) /// table and the value of the <code>@MapKey</code> annotation, if there was one. /// </param> public CollectionMetadataGenerator(IMetaDataStore metaDataStore, AuditMetadataGenerator mainGenerator, Mapping.Collection propertyValue, ICompositeMapperBuilder currentMapper, string referencingEntityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData) { _metaDataStore = metaDataStore; _mainGenerator = mainGenerator; _propertyValue = propertyValue; _currentMapper = currentMapper; _referencingEntityName = referencingEntityName; _xmlMappingData = xmlMappingData; _propertyAuditingData = propertyAuditingData; _propertyName = propertyAuditingData.Name; _referencingEntityConfiguration = mainGenerator.EntitiesConfigurations[referencingEntityName]; if (_referencingEntityConfiguration == null) { throw new MappingException("Unable to read auditing configuration for " + referencingEntityName + "!"); } _referencedEntityName = MappingTools.ReferencedEntityName(propertyValue.Element); }
public OneToManyPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) { _cascadeDeleteEnabled = collection.Key.IsCascadeDeleteEnabled && factory.Dialect.SupportsCascadeDelete; _keyIsNullable = collection.Key.IsNullable; _keyIsUpdateable = collection.Key.IsUpdateable; }
private void BindManyToMany(HbmManyToMany manyToManyMapping, Mapping.Collection model) { var manyToMany = new ManyToOne(model.CollectionTable); model.Element = manyToMany; new ValuePropertyBinder(manyToMany, Mappings).BindSimpleValue(manyToManyMapping, Mapping.Collection.DefaultElementColumnName, false); InitOuterJoinFetchSetting(manyToManyMapping, manyToMany); var restrictedLaziness = manyToManyMapping.lazySpecified ? manyToManyMapping.lazy : (HbmRestrictedLaziness?)null; InitLaziness(restrictedLaziness, manyToMany, true); if (!string.IsNullOrEmpty(manyToManyMapping.propertyref)) { manyToMany.ReferencedPropertyName = manyToManyMapping.propertyref; } manyToMany.ReferencedEntityName = GetEntityName(manyToManyMapping, mappings); manyToMany.IsIgnoreNotFound = manyToManyMapping.NotFoundMode == HbmNotFoundMode.Ignore; if (!string.IsNullOrEmpty(manyToManyMapping.foreignkey)) { manyToMany.ForeignKeyName = manyToManyMapping.foreignkey; } BindManyToManySubelements(manyToManyMapping, model); }
private void BindKey(HbmKey keyMapping, Mapping.Collection model) { if (keyMapping == null) { return; } string propRef = model.ReferencedPropertyName; IKeyValue keyValue; if (propRef == null) { keyValue = model.Owner.Identifier; } else { keyValue = (IKeyValue)model.Owner.GetProperty(propRef).Value; } var key = new DependantValue(model.CollectionTable, keyValue) { IsCascadeDeleteEnabled = keyMapping.ondelete == HbmOndelete.Cascade }; new ValuePropertyBinder(key, Mappings).BindSimpleValue(keyMapping, Mapping.Collection.DefaultKeyColumnName, model.IsOneToMany); if (key.Type.ReturnedClass.IsArray) { throw new MappingException("illegal use of an array as an identifier (arrays don't reimplement Equals)"); } model.Key = key; key.SetNullable(!keyMapping.IsNullable.HasValue || keyMapping.IsNullable.Value); key.SetUpdateable(!keyMapping.IsUpdatable.HasValue || keyMapping.IsUpdatable.Value); BindForeignKey(keyMapping.foreignkey, key); }
private static void PreCollectionSecondPass(Mapping.Collection collection) { if (log.IsDebugEnabled) { log.Debug("Second pass for collection: " + collection.Role); } }
private void HandleCustomSQL(ICollectionSqlsMapping collection, Mapping.Collection model) { var sqlInsert = collection.SqlInsert; if (sqlInsert != null) { bool callable = sqlInsert.callableSpecified && sqlInsert.callable; model.SetCustomSQLInsert(sqlInsert.Text.LinesToString(), callable, GetResultCheckStyle(sqlInsert)); } var sqlDelete = collection.SqlDelete; if (sqlDelete != null) { bool callable = sqlDelete.callableSpecified && sqlDelete.callable; model.SetCustomSQLDelete(sqlDelete.Text.LinesToString(), callable, GetResultCheckStyle(sqlDelete)); } var sqlUpdate = collection.SqlUpdate; if (sqlUpdate != null) { bool callable = sqlUpdate.callableSpecified && sqlUpdate.callable; model.SetCustomSQLUpdate(sqlUpdate.Text.LinesToString(), callable, GetResultCheckStyle(sqlUpdate)); } var sqlDeleteAll = collection.SqlDeleteAll; if (sqlDeleteAll != null) { bool callable = sqlDeleteAll.callableSpecified && sqlDeleteAll.callable; model.SetCustomSQLDeleteAll(sqlDeleteAll.Text.LinesToString(), callable, GetResultCheckStyle(sqlDeleteAll)); } }
private void InitLaziness(ICollectionPropertiesMapping collectionMapping, Mapping.Collection fetchable) { var lazyMapping = collectionMapping.Lazy; if (!lazyMapping.HasValue) { fetchable.IsLazy = mappings.DefaultLazy; fetchable.ExtraLazy = false; return; } switch (lazyMapping.Value) { case HbmCollectionLazy.True: fetchable.IsLazy = true; break; case HbmCollectionLazy.False: fetchable.IsLazy = false; fetchable.ExtraLazy = false; break; case HbmCollectionLazy.Extra: fetchable.IsLazy = true; fetchable.ExtraLazy = true; break; default: throw new ArgumentOutOfRangeException(); } }
private void BindManyToManySubelements(HbmManyToMany manyToManyMapping, Mapping.Collection collection) { // Bind the where string whereCondition = string.IsNullOrEmpty(manyToManyMapping.where) ? null : manyToManyMapping.where; collection.ManyToManyWhere = whereCondition; // Bind the order-by string orderFragment = string.IsNullOrEmpty(manyToManyMapping.orderby) ? null : manyToManyMapping.orderby; collection.ManyToManyOrdering = orderFragment; // Bind the filters var filters = manyToManyMapping.filter; var hasFilters = filters != null && filters.Length > 0; if ((hasFilters || whereCondition != null) && collection.FetchMode == FetchMode.Join && collection.Element.FetchMode != FetchMode.Join) { throw new MappingException( string.Format( "many-to-many defining filter or where without join fetching not valid within collection using join fetching [{0}]", collection.Role)); } new FiltersBinder(collection, Mappings).Bind(filters, collection.AddManyToManyFilter); }
private static void BindCache(HbmCache cacheSchema, Mapping.Collection collection) { if (cacheSchema != null) { collection.CacheConcurrencyStrategy = cacheSchema.usage.ToCacheConcurrencyStrategy(); collection.CacheRegionName = cacheSchema.region; } }
/// <summary> /// /// </summary> /// <param name="collection"></param> public void AddCollection(Mapping.Collection collection) { if (collections.ContainsKey(collection.Role)) { throw new DuplicateMappingException("collection role", collection.Role); } collections[collection.Role] = collection; }
private void AddCollectionSecondPass(XmlNode node, Mapping.Collection model, IDictionary <string, MetaAttribute> inheritedMetas) { mappings.AddSecondPass(delegate(IDictionary <string, PersistentClass> persistentClasses) { PreCollectionSecondPass(model); BindCollectionSecondPass(node, model, persistentClasses, inheritedMetas); PostCollectionSecondPass(model); }); }
/// <summary> /// /// </summary> /// <param name="collection"></param> public void AddCollection(Mapping.Collection collection) { object old = collections[collection.Role]; if (old != null) { log.Warn("duplicate collection role: " + collection.Role); } collections[collection.Role] = collection; }
public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory, Configuration cfg) { ConstructorInfo pc; var use4Parameters = false; try { pc = persisterClass.GetConstructor(CollectionPersisterConstructorArgs); if (pc == null) { use4Parameters = true; pc = persisterClass.GetConstructor(CollectionPersisterConstructor2Args); } } catch (Exception e) { throw new MappingException("Could not get constructor for " + persisterClass.Name, e); } if (pc == null) { var messageBuilder = new StringBuilder(); messageBuilder.AppendLine("Could not find a public constructor for " + persisterClass.Name + ";"); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructorArgs.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructorArgs, t => messageBuilder.AppendLine(t.FullName)); messageBuilder.AppendLine(); messageBuilder.AppendLine("- The ctor may have " + CollectionPersisterConstructor2Args.Length + " parameters of types (in order):"); System.Array.ForEach(CollectionPersisterConstructor2Args, t => messageBuilder.AppendLine(t.FullName)); throw new MappingException(messageBuilder.ToString()); } try { if (!use4Parameters) { return((ICollectionPersister)pc.Invoke(new object[] { model, cache, factory })); } return((ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory })); } catch (TargetInvocationException tie) { Exception e = tie.InnerException; if (e is HibernateException) { throw e; } else { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } } catch (Exception e) { throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); } }
private static string searchMappedBy(PersistentClass referencedClass, Mapping.Collection collectionValue) { foreach (var property in referencedClass.PropertyIterator) { //should probably not care if order is same... if (property.Value.ColumnIterator.SequenceEqual(collectionValue.Key.ColumnIterator)) { return(property.Name); } } return(null); }
private void BindManyToManySubelements(Mapping.Collection collection, XmlNode manyToManyNode) { // Bind the where XmlAttribute where = manyToManyNode.Attributes["where"]; string whereCondition = where == null ? null : where.Value; collection.ManyToManyWhere = whereCondition; // Bind the order-by XmlAttribute order = manyToManyNode.Attributes["order-by"]; string orderFragment = order == null ? null : order.Value; collection.ManyToManyOrdering = orderFragment; // Bind the filters if ((manyToManyNode.SelectSingleNode(HbmConstants.nsFilter, namespaceManager) != null || whereCondition != null) && collection.FetchMode == FetchMode.Join && collection.Element.FetchMode != FetchMode.Join) { throw new MappingException( "many-to-many defining filter or where without join fetching " + "not valid within collection using join fetching [" + collection.Role + "]" ); } foreach (XmlNode filterElement in manyToManyNode.SelectNodes(HbmConstants.nsFilter, namespaceManager)) { string name = XmlHelper.GetAttributeValue(filterElement, "name"); string condition = filterElement.InnerText.Trim(); if (StringHelper.IsEmpty(condition)) { condition = XmlHelper.GetAttributeValue(filterElement, "condition"); } if (StringHelper.IsEmpty(condition)) { condition = mappings.GetFilterDefinition(name).DefaultFilterCondition; } if (condition == null) { throw new MappingException("no filter condition found for filter: " + name); } log.Debug( "Applying many-to-many filter [" + name + "] as [" + condition + "] to role [" + collection.Role + "]" ); collection.AddManyToManyFilter(name, condition); } }
public static ICollectionPersister CreateCollectionPersister(Mapping.Collection model, ISessionFactoryImplementor factory) { System.Type persisterClass = model.CollectionPersisterClass; if (persisterClass == null) { // default behaviour return(model.IsOneToMany ? (ICollectionPersister) new OneToManyPersister(model, factory) : (ICollectionPersister) new BasicCollectionPersister(model, factory)); } else { return(Create(persisterClass, model, factory)); } }
private void BindManyToAny(HbmManyToAny manyToAnyMapping, Mapping.Collection model) { var any = new Any(model.CollectionTable); model.Element = any; any.IdentifierTypeName = manyToAnyMapping.idtype; new TypeBinder(any, Mappings).Bind(manyToAnyMapping.idtype); BindAnyMeta(manyToAnyMapping, any); new ColumnsBinder(any, Mappings).Bind(manyToAnyMapping.Columns, true, () => new HbmColumn { name = mappings.NamingStrategy.PropertyToColumnName(manyToAnyMapping.column1) }); }
private String GetMiddleTableName(Mapping.Collection value, String entityName) { // We check how Hibernate maps the collection. if (value.Element is OneToMany && !value.IsInverse) { // This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a // middle table for mapping this relation. String refEntName = MappingTools.getReferencedEntityName(value.Element); return(entityName.Substring(entityName.LastIndexOf(".") + 1) + "_" + refEntName.Substring(refEntName.LastIndexOf(".") + 1)); } else { // Hibernate uses a middle table for mapping this relation, so we get it's name directly. return(value.CollectionTable.Name); } }
private void BindElement(HbmElement elementMapping, Mapping.Collection model) { var element = new SimpleValue(model.CollectionTable); model.Element = element; if (model.IsGeneric) { switch (model.GenericArguments.Length) { case 1: // a collection with a generic type parameter element.TypeName = model.GenericArguments[0].AssemblyQualifiedName; break; case 2: // a map (IDictionary) with 2 parameters element.TypeName = model.GenericArguments[1].AssemblyQualifiedName; break; } } new ValuePropertyBinder(element, Mappings).BindSimpleValue(elementMapping, Mapping.Collection.DefaultKeyColumnName, true); }
/** * @param mainGenerator Main generator, giving access to configuration and the basic mapper. * @param propertyValue Value of the collection, as mapped by Hibernate. * @param currentMapper Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper} * will be added. * @param referencingEntityName Name of the entity that owns this collection. * @param xmlMappingData In case this collection requires a middle table, additional mapping documents will * be created using this object. * @param propertyAuditingData Property auditing (meta-)data. Among other things, holds the name of the * property that references the collection in the referencing entity, the user data for middle (join) * table and the value of the <code>@MapKey</code> annotation, if there was one. */ public CollectionMetadataGenerator(AuditMetadataGenerator mainGenerator, Mapping.Collection propertyValue, ICompositeMapperBuilder currentMapper, String referencingEntityName, EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData) { this.mainGenerator = mainGenerator; this.propertyValue = propertyValue; this.currentMapper = currentMapper; this.referencingEntityName = referencingEntityName; this.xmlMappingData = xmlMappingData; this.propertyAuditingData = propertyAuditingData; this.propertyName = propertyAuditingData.Name; referencingEntityConfiguration = mainGenerator.EntitiesConfigurations[referencingEntityName]; if (referencingEntityConfiguration == null) { throw new MappingException("Unable to read auditing configuration for " + referencingEntityName + "!"); } referencedEntityName = MappingTools.getReferencedEntityName(propertyValue.Element); }
private string getMappedBy(Mapping.Collection collectionValue) { var referencedClass = _mainGenerator.Cfg.GetClassMapping(MappingTools.ReferencedEntityName(collectionValue.Element)); var mappedBy = searchMappedBy(referencedClass, collectionValue); if (mappedBy == null) { log.Debug("Going to search the mapped by attribute for " + _propertyName + " in superclasses of entity: " + referencedClass.ClassName); var tempClass = referencedClass; while (mappedBy == null && tempClass.Superclass != null) { log.Debug("Searching in superclass: " + tempClass.Superclass.ClassName); mappedBy = searchMappedBy(tempClass.Superclass, collectionValue); tempClass = tempClass.Superclass; } } if (mappedBy == null) { throw new MappingException("Cannot find the inverse side for " + _propertyName + " in " + _referencingEntityName + "!"); } return(mappedBy); }
private static void PostCollectionSecondPass(Mapping.Collection collection) { collection.CreateAllKeys(); if (log.IsDebugEnabled) { string msg = "Mapped collection key: " + string.Join(",", collection.Key.ColumnIterator.Select(c => c.Text).ToArray()); if (collection.IsIndexed) { msg += ", index: " + string.Join(",", ((IndexedCollection)collection).Index.ColumnIterator.Select(c => c.Text).ToArray()); } if (collection.IsOneToMany) { msg += ", one-to-many: " + collection.Element.Type.Name; } else { msg += ", element: " + string.Join(",", collection.Element.ColumnIterator.Select(c => c.Text).ToArray()); msg += ", type: " + collection.Element.Type.Name; } log.Debug(msg); } }
public void ConfigureCacheOfCollection() { Configuration configure = new Configuration().Configure(); configure.AddResource("NHibernate.Test.CfgTest.Loquacious.EntityToCache.hbm.xml", GetType().Assembly); configure.EntityCache <EntityToCache>(ce => { ce.Strategy = EntityCacheUsage.NonStrictReadWrite; ce.RegionName = "MyRegion"; ce.Collection(e => e.Elements, cc => { cc.RegionName = "MyCollectionRegion"; cc.Strategy = EntityCacheUsage.NonStrictReadWrite; }); }); Mapping.Collection pc = configure.GetCollectionMapping("NHibernate.Test.CfgTest.Loquacious.EntityToCache.Elements"); Assert.That(pc.CacheConcurrencyStrategy, Is.EqualTo(EntityCacheUsageParser.ToString(EntityCacheUsage.NonStrictReadWrite))); Assert.That(pc.CacheRegionName, Is.EqualTo("MyCollectionRegion")); }
private static void PostCollectionSecondPass(Mapping.Collection collection) { collection.CreateAllKeys(); if (log.IsDebugEnabled) { string msg = "Mapped collection key: " + Columns(collection.Key); if (collection.IsIndexed) { msg += ", index: " + Columns(((IndexedCollection)collection).Index); } if (collection.IsOneToMany) { msg += ", one-to-many: " + collection.Element.Type.Name; } else { msg += ", element: " + Columns(collection.Element); msg += ", type: " + collection.Element.Type.Name; } log.Debug(msg); } }
public void CollectionFetchVsLoad() { IStatistics stats = Sfi.Statistics; stats.Clear(); ISession s = OpenSession(); ITransaction tx = s.BeginTransaction(); Continent europe = FillDb(s); tx.Commit(); s.Clear(); tx = s.BeginTransaction(); Assert.AreEqual(0, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount); Continent europe2 = s.Get <Continent>(europe.Id); Assert.AreEqual(0, stats.CollectionLoadCount, "Lazy true: no collection should be loaded"); Assert.AreEqual(0, stats.CollectionFetchCount); int cc = europe2.Countries.Count; Assert.AreEqual(1, stats.CollectionLoadCount); Assert.AreEqual(1, stats.CollectionFetchCount, "Explicit fetch of the collection state"); tx.Commit(); s.Close(); s = OpenSession(); tx = s.BeginTransaction(); stats.Clear(); europe = FillDb(s); tx.Commit(); s.Clear(); tx = s.BeginTransaction(); Assert.AreEqual(0, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount); europe2 = s.CreateQuery("from Continent a join fetch a.Countries where a.id = " + europe.Id).UniqueResult <Continent>(); Assert.AreEqual(1, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount, "collection should be loaded in the same query as its parent"); tx.Commit(); s.Close(); Mapping.Collection coll = cfg.GetCollectionMapping("NHibernate.Test.Stats.Continent.Countries"); coll.FetchMode = FetchMode.Join; coll.IsLazy = false; ISessionFactory sf = cfg.BuildSessionFactory(); stats = sf.Statistics; stats.Clear(); stats.IsStatisticsEnabled = true; s = sf.OpenSession(); tx = s.BeginTransaction(); europe = FillDb(s); tx.Commit(); s.Clear(); tx = s.BeginTransaction(); Assert.AreEqual(0, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount); europe2 = s.Get <Continent>(europe.Id); Assert.AreEqual(1, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount, "Should do direct load, not indirect second load when lazy false and JOIN"); tx.Commit(); s.Close(); sf.Close(); coll = cfg.GetCollectionMapping("NHibernate.Test.Stats.Continent.Countries"); coll.FetchMode = FetchMode.Select; coll.IsLazy = false; sf = cfg.BuildSessionFactory(); stats = sf.Statistics; stats.Clear(); stats.IsStatisticsEnabled = true; s = sf.OpenSession(); tx = s.BeginTransaction(); europe = FillDb(s); tx.Commit(); s.Clear(); tx = s.BeginTransaction(); Assert.AreEqual(0, stats.CollectionLoadCount); Assert.AreEqual(0, stats.CollectionFetchCount); europe2 = s.Get <Continent>(europe.Id); Assert.AreEqual(1, stats.CollectionLoadCount); Assert.AreEqual(1, stats.CollectionFetchCount, "Should do explicit collection load, not part of the first one"); foreach (Country country in europe2.Countries) { s.Delete(country); } CleanDb(s); tx.Commit(); s.Close(); }
public CollectionSecondPass(Mappings mappings, Mapping.Collection collection) { this.collection = collection; this.mappings = mappings; }
public BasicCollectionPersister(Mapping.Collection collection, ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) : base(collection, cache, cfg, factory) { }
public AbstractSecondPass( XmlNode node, Mappings mappings, Mapping.Collection collection ) { this.node = node; this.collection = collection; this.mappings = mappings; }
private void BindCompositeElement(HbmCompositeElement compositeElementMapping, Mapping.Collection model, IDictionary <string, MetaAttribute> inheritedMetas) { var component = new Component(model); model.Element = component; BindComponent(compositeElementMapping, component, null, null, model.Role + ".element", true, inheritedMetas); }
/// <remarks> /// Called for all collections /// </remarks> private void BindCollectionSecondPass(XmlNode node, Mapping.Collection model, IDictionary <string, PersistentClass> persistentClasses, IDictionary <string, MetaAttribute> inheritedMetas) { if (model.IsOneToMany) { OneToMany oneToMany = (OneToMany)model.Element; string associatedEntityName = oneToMany.ReferencedEntityName; PersistentClass persistentClass; if (persistentClasses.TryGetValue(associatedEntityName, out persistentClass) == false) { throw new MappingException("Association references unmapped class: " + associatedEntityName); } oneToMany.AssociatedClass = persistentClass; model.CollectionTable = persistentClass.Table; if (log.IsInfoEnabled) { log.Info("mapping collection: " + model.Role + " -> " + model.CollectionTable.Name); } } //CHECK XmlAttribute chNode = node.Attributes["check"]; if (chNode != null) { model.CollectionTable.AddCheckConstraint(chNode.Value); } //contained elements: foreach (XmlNode subnode in node.ChildNodes) { //I am only concerned with elements that are from the nhibernate namespace if (subnode.NamespaceURI != Configuration.MappingSchemaXMLNS) { continue; } string name = subnode.LocalName; //.Name; if ("key".Equals(name) || "generated-key".Equals(name)) { string propRef = model.ReferencedPropertyName; IKeyValue keyValue; if (propRef == null) { keyValue = model.Owner.Identifier; } else { keyValue = (IKeyValue)model.Owner.GetProperty(propRef).Value; } DependantValue key = new DependantValue(model.CollectionTable, keyValue); if (subnode.Attributes["on-delete"] != null) { key.IsCascadeDeleteEnabled = "cascade".Equals(subnode.Attributes["on-delete"].Value); } BindSimpleValue(subnode, key, model.IsOneToMany, Mapping.Collection.DefaultKeyColumnName); if (key.Type.ReturnedClass.IsArray) { throw new MappingException("illegal use of an array as an identifier (arrays don't reimplement Equals)"); } model.Key = key; XmlAttribute notNull = subnode.Attributes["not-null"]; key.SetNullable(notNull == null || IsFalse(notNull.Value)); XmlAttribute updateable = subnode.Attributes["update"]; key.SetUpdateable(updateable == null || IsTrue(updateable.Value)); } else if ("element".Equals(name)) { var elt = new SimpleValue(model.CollectionTable); model.Element = elt; if (model.IsGeneric) { switch (model.GenericArguments.Length) { case 1: // a collection with a generic type parameter elt.TypeName = model.GenericArguments[0].AssemblyQualifiedName; break; case 2: // a map (IDictionary) with 2 parameters elt.TypeName = model.GenericArguments[1].AssemblyQualifiedName; break; } } BindSimpleValue(subnode, elt, true, Mapping.Collection.DefaultElementColumnName); } else if ("many-to-many".Equals(name)) { ManyToOne element = new ManyToOne(model.CollectionTable); model.Element = element; BindManyToOne(subnode, element, Mapping.Collection.DefaultElementColumnName, false); BindManyToManySubelements(model, subnode); } else if ("composite-element".Equals(name)) { Component element = new Component(model); model.Element = element; BindComponent(subnode, element, null, null, null, model.Role + ".element", true, inheritedMetas); } else if ("many-to-any".Equals(name)) { Any element = new Any(model.CollectionTable); model.Element = element; BindAny(subnode, element, true); } else if ("jcs-cache".Equals(name) || "cache".Equals(name)) { XmlAttribute usageNode = subnode.Attributes["usage"]; model.CacheConcurrencyStrategy = (usageNode != null) ? usageNode.Value : null; XmlAttribute regionNode = subnode.Attributes["region"]; model.CacheRegionName = (regionNode != null) ? regionNode.Value : null; } } }
/// <remarks> /// Called for all collections. <paramref name="containingType" /> parameter /// was added in NH to allow for reflection related to generic types. /// </remarks> private void BindCollection(XmlNode node, Mapping.Collection model, string className, string path, System.Type containingType, IDictionary <string, MetaAttribute> inheritedMetas) { // ROLENAME model.Role = StringHelper.Qualify(className, path); // TODO: H3.1 has just collection.setRole(path) here - why? XmlAttribute inverseNode = node.Attributes["inverse"]; if (inverseNode != null) { model.IsInverse = StringHelper.BooleanValue(inverseNode.Value); } // TODO: H3.1 - not ported: mutable XmlAttribute olNode = node.Attributes["optimistic-lock"]; model.IsOptimisticLocked = olNode == null || "true".Equals(olNode.Value); XmlAttribute orderNode = node.Attributes["order-by"]; if (orderNode != null) { model.OrderBy = orderNode.Value; } XmlAttribute whereNode = node.Attributes["where"]; if (whereNode != null) { model.Where = whereNode.Value; } XmlAttribute batchNode = node.Attributes["batch-size"]; if (batchNode != null) { model.BatchSize = int.Parse(batchNode.Value); } // PERSISTER XmlAttribute persisterNode = node.Attributes["persister"]; if (persisterNode == null) { //persister = CollectionPersisterImpl.class; } else { model.CollectionPersisterClass = ClassForNameChecked( persisterNode.Value, mappings, "could not instantiate collection persister class: {0}"); } XmlAttribute typeNode = node.Attributes["collection-type"]; if (typeNode != null) { string typeName = typeNode.Value; TypeDef typeDef = mappings.GetTypeDef(typeName); if (typeDef != null) { model.TypeName = typeDef.TypeClass; model.TypeParameters = typeDef.Parameters; } else { model.TypeName = FullQualifiedClassName(typeName, mappings); } } // FETCH STRATEGY InitOuterJoinFetchSetting(node, model); if ("subselect".Equals(XmlHelper.GetAttributeValue(node, "fetch"))) { model.IsSubselectLoadable = true; model.Owner.HasSubselectLoadableCollections = true; } // LAZINESS InitLaziness(node, model, "true", mappings.DefaultLazy); XmlAttribute lazyNode = node.Attributes["lazy"]; if (lazyNode != null && "extra".Equals(lazyNode.Value)) { model.IsLazy = true; model.ExtraLazy = true; } XmlNode oneToManyNode = node.SelectSingleNode(HbmConstants.nsOneToMany, namespaceManager); if (oneToManyNode != null) { OneToMany oneToMany = new OneToMany(model.Owner); model.Element = oneToMany; BindOneToMany(oneToManyNode, oneToMany); //we have to set up the table later!! yuck } else { //TABLE XmlAttribute tableNode = node.Attributes["table"]; string tableName; if (tableNode != null) { tableName = mappings.NamingStrategy.TableName(tableNode.Value); } else { tableName = mappings.NamingStrategy.PropertyToTableName(className, path); } XmlAttribute schemaNode = node.Attributes["schema"]; string schema = schemaNode == null ? mappings.SchemaName : schemaNode.Value; XmlAttribute catalogNode = node.Attributes["catalog"]; string catalog = catalogNode == null ? mappings.CatalogName : catalogNode.Value; XmlAttribute actionNode = node.Attributes["schema-action"]; string action = actionNode == null ? "all" : actionNode.Value; model.CollectionTable = mappings.AddTable(schema, catalog, tableName, null, false, action); log.InfoFormat("Mapping collection: {0} -> {1}", model.Role, model.CollectionTable.Name); } //SORT XmlAttribute sortedAtt = node.Attributes["sort"]; // unsorted, natural, comparator.class.name if (sortedAtt == null || sortedAtt.Value.Equals("unsorted")) { model.IsSorted = false; } else { model.IsSorted = true; if (!sortedAtt.Value.Equals("natural")) { string comparatorClassName = FullQualifiedClassName(sortedAtt.Value, mappings); model.ComparerClassName = comparatorClassName; } } //ORPHAN DELETE (used for programmer error detection) XmlAttribute cascadeAtt = node.Attributes["cascade"]; if (cascadeAtt != null && cascadeAtt.Value.IndexOf("delete-orphan") >= 0) { model.HasOrphanDelete = true; } bool?isGeneric = null; XmlAttribute genericAtt = node.Attributes["generic"]; if (genericAtt != null) { isGeneric = bool.Parse(genericAtt.Value); } System.Type collectionType = null; if (!isGeneric.HasValue && containingType != null) { collectionType = GetPropertyType(node, containingType, GetPropertyName(node)); isGeneric = collectionType.IsGenericType; } model.IsGeneric = isGeneric ?? false; if (model.IsGeneric) { // Determine the generic arguments using reflection if (collectionType == null) { collectionType = GetPropertyType(node, containingType, GetPropertyName(node)); } System.Type[] genericArguments = collectionType.GetGenericArguments(); model.GenericArguments = genericArguments; } HandleCustomSQL(node, model); //set up second pass if (model is List) { AddListSecondPass(node, (List)model, inheritedMetas); } else if (model is Map) { AddMapSecondPass(node, (Map)model, inheritedMetas); } else if (model is Set) { AddSetSecondPass(node, (Set)model, inheritedMetas); } else if (model is IdentifierCollection) { AddIdentifierCollectionSecondPass(node, (IdentifierCollection)model, inheritedMetas); } else { AddCollectionSecondPass(node, model, inheritedMetas); } foreach (XmlNode filter in node.SelectNodes(HbmConstants.nsFilter, namespaceManager)) { ParseFilter(filter, model); } XmlNode loader = node.SelectSingleNode(HbmConstants.nsLoader, namespaceManager); if (loader != null) { model.LoaderName = XmlHelper.GetAttributeValue(loader, "query-ref"); } XmlNode key = node.SelectSingleNode(HbmConstants.nsKey, namespaceManager); if (key != null) { model.ReferencedPropertyName = XmlHelper.GetAttributeValue(key, "property-ref"); } }