Пример #1
0
		public FromElementType(FromElement fromElement, IEntityPersister persister, EntityType entityType)
		{
			_fromElement = fromElement;
			_persister = persister;
			_entityType = entityType;

			var queryable = persister as IQueryable;
			if (queryable != null)
				fromElement.Text = queryable.TableName + " " + fromElement.TableAlias;
		}
Пример #2
0
		public FromElementType(FromElement fromElement, IEntityPersister persister, EntityType entityType)
		{
			_fromElement = fromElement;
			_persister = persister;
			_entityType = entityType;

			if (persister != null)
			{
				fromElement.Text = ((IQueryable)persister).TableName + " " + TableAlias;
			}
		}
Пример #3
0
        /// <summary>
        ///  Visit a many-to-one or one-to-one associated entity. Default superclass implementation is a no-op.
        /// </summary>
        /// <param name="value"></param>
        /// <param name="entityType"></param>
        /// <returns></returns>
        internal override object ProcessEntity(object value, EntityType entityType)
        {
            if (value != null)
            {
                Session.PersistenceContext.ReassociateIfUninitializedProxy(value);
                // if it is an initialized proxy, let cascade
                // handle it later on
            }

            return null;
        }
Пример #4
0
		private void DereferenceEntity(EntityType entityType, bool implicitJoin, string classAlias, bool generateJoin, IASTNode parent) 
		{
			CheckForCorrelatedSubquery( "dereferenceEntity" );

			// three general cases we check here as to whether to render a physical SQL join:
			// 1) is our parent a DotNode as well?  If so, our property reference is
			// 		being further de-referenced...
			// 2) is this a DML statement
			// 3) we were asked to generate any needed joins (generateJoins==true) *OR*
			//		we are currently processing a select or from clause
			// (an additional check is the REGRESSION_STYLE_JOIN_SUPPRESSION check solely intended for the test suite)
			//
			// The REGRESSION_STYLE_JOIN_SUPPRESSION is an additional check
			// intended solely for use within the test suite.  This forces the
			// implicit join resolution to behave more like the classic parser.
			// The underlying issue is that classic translator is simply wrong
			// about its decisions on whether or not to render an implicit join
			// into a physical SQL join in a lot of cases.  The piece it generally
			// tends to miss is that INNER joins effect the results by further
			// restricting the data set!  A particular manifestation of this is
			// the fact that the classic translator will skip the physical join
			// for ToOne implicit joins *if the query is shallow*; the result
			// being that Query.list() and Query.iterate() could return
			// different number of results!

			DotNode parentAsDotNode = null;
			string property = _propertyName;
			bool joinIsNeeded;

			if ( IsDotNode( parent ) ) 
			{
				// our parent is another dot node, meaning we are being further dereferenced.
				// thus we need to generate a join unless the parent refers to the associated
				// entity's PK (because 'our' table would know the FK).
				parentAsDotNode = ( DotNode ) parent;
				property = parentAsDotNode._propertyName;
				joinIsNeeded = generateJoin && !IsReferenceToPrimaryKey( parentAsDotNode._propertyName, entityType );
			}
			else if ( ! Walker.IsSelectStatement ) 
			{
				// in non-select queries, the only time we should need to join is if we are in a subquery from clause
				joinIsNeeded = Walker.CurrentStatementType == HqlSqlWalker.SELECT && Walker.IsInFrom;
			}
			else if ( REGRESSION_STYLE_JOIN_SUPPRESSION ) {
				// this is the regression style determination which matches the logic of the classic translator
				joinIsNeeded = generateJoin && ( !Walker.IsInSelect || !Walker.IsShallowQuery);
			}
			else 
			{
				joinIsNeeded = generateJoin || ( Walker.IsInSelect || Walker.IsInFrom );
			}

			if ( joinIsNeeded ) 
			{
				DereferenceEntityJoin( classAlias, entityType, implicitJoin, parent );
			}
			else 
			{
				DereferenceEntityIdentifier( property, parentAsDotNode );
			}
		}
 /// <summary>Add the parent-child relationship for certain propType conditions</summary>
 private void MaybeAddToGraph(EntityInfo child, EntityInfo parent, EntityType propType)
 {
     if (!(propType.IsOneToOne && propType.UseLHSPrimaryKey && (propType.ForeignKeyDirection == ForeignKeyDirection.ForeignKeyToParent)))
     {
         AddToGraph(child, parent);
     }
 }
        /// <summary>
        /// Set an association value based on the value of the foreign key.  This updates the property of the entity.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        private void FixupRelationship(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            var entity = entityInfo.Entity;
            if (removeMode)
            {
                meta.SetPropertyValue(entity, propName, null, EntityMode.Poco);
                return;
            }
            object relatedEntity = GetPropertyValue(meta, entity, propName);
            if (relatedEntity != null)
            {
                // entities are already connected - still need to add to dependency graph
                EntityInfo relatedEntityInfo = FindInSaveMapByEntity(propType.ReturnedClass, relatedEntity);
                MaybeAddToGraph(entityInfo, relatedEntityInfo, propType);
                return;
            }

            relatedEntity = GetRelatedEntity(propName, propType, entityInfo, meta);

            if (relatedEntity != null)
                meta.SetPropertyValue(entity, propName, relatedEntity, EntityMode.Poco);
        }
		/// <summary>
		/// 
		/// </summary>
		/// <param name="path"></param>
		/// <param name="etype"></param>
		/// <param name="columns"></param>
		/// <param name="factory"></param>
		protected void InitIdentifierPropertyPaths( string path, EntityType etype, string[] columns, ISessionFactoryImplementor factory )
		{
			IType idtype = etype.GetIdentifierOrUniqueKeyType( factory );

			if ( !etype.IsUniqueKeyReference )
			{
				string idpath1 = ExtendPath( path, PathExpressionParser.EntityID );
				AddPropertyPath( idpath1, idtype, columns );
				InitPropertyPaths( idpath1, idtype, columns, factory );
			}

			string idPropName = etype.GetIdentifierOrUniqueKeyPropertyName( factory );
			if ( idPropName!=null )
			{
				string idpath2 = ExtendPath( path, idPropName );
				AddPropertyPath( idpath2, idtype, columns );
				InitPropertyPaths( idpath2, idtype, columns, factory );
			}
		}
		protected void InitIdentifierPropertyPaths(string path, EntityType etype, string[] columns, IMapping factory)
		{
			IType idtype = etype.GetIdentifierOrUniqueKeyType(factory);
			string idPropName = etype.GetIdentifierOrUniqueKeyPropertyName(factory);
			bool hasNonIdentifierPropertyNamedId = HasNonIdentifierPropertyNamedId(etype, factory);

			if (etype.IsReferenceToPrimaryKey)
			{
				if (!hasNonIdentifierPropertyNamedId)
				{
					string idpath1 = ExtendPath(path, EntityPersister.EntityID);
					AddPropertyPath(idpath1, idtype, columns, null);
					InitPropertyPaths(idpath1, idtype, columns, null, factory);
				}
			}

			if (idPropName != null)
			{
				string idpath2 = ExtendPath(path, idPropName);
				AddPropertyPath(idpath2, idtype, columns, null);
				InitPropertyPaths(idpath2, idtype, columns, null, factory);
			}
		}
Пример #9
0
		public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory)
		{
			this.sessionFactory = sessionFactory;


			name = persistentClass.EntityName;
			rootName = persistentClass.RootClazz.EntityName;
			entityType = TypeFactory.ManyToOne(name);
			type = persistentClass.MappedClass;
			rootType = persistentClass.RootClazz.MappedClass;
			rootTypeAssemblyQualifiedName = rootType.AssemblyQualifiedName;

			identifierProperty =
				PropertyFactory.BuildIdentifierProperty(persistentClass, sessionFactory.GetIdentifierGenerator(rootType));

			versioned = persistentClass.IsVersioned;

			bool lazyAvailable = persistentClass.HasPocoRepresentation && FieldInterceptionHelper.IsInstrumented(persistentClass.MappedClass);
			bool hasLazy = false;

			propertySpan = persistentClass.PropertyClosureSpan;
			properties = new StandardProperty[propertySpan];
			List<int> naturalIdNumbers = new List<int>();

			#region temporary

			propertyNames = new string[propertySpan];
			propertyTypes = new IType[propertySpan];
			propertyUpdateability = new bool[propertySpan];
			propertyInsertability = new bool[propertySpan];
			insertInclusions = new ValueInclusion[propertySpan];
			updateInclusions = new ValueInclusion[propertySpan];
			nonlazyPropertyUpdateability = new bool[propertySpan];
			propertyCheckability = new bool[propertySpan];
			propertyNullability = new bool[propertySpan];
			propertyVersionability = new bool[propertySpan];
			propertyLaziness = new bool[propertySpan];
			cascadeStyles = new CascadeStyle[propertySpan];

			#endregion


			int i = 0;
			int tempVersionProperty = NoVersionIndex;
			bool foundCascade = false;
			bool foundCollection = false;
			bool foundMutable = false;
			bool foundInsertGeneratedValue = false;
			bool foundUpdateGeneratedValue = false;
			bool foundNonIdentifierPropertyNamedId = false;

			foreach (Mapping.Property prop in persistentClass.PropertyClosureIterator)
			{
				if (prop == persistentClass.Version)
				{
					tempVersionProperty = i;
					properties[i] = PropertyFactory.BuildVersionProperty(prop, lazyAvailable);
				}
				else
				{
					properties[i] = PropertyFactory.BuildStandardProperty(prop, lazyAvailable);
				}

				if (prop.IsNaturalIdentifier)
				{
					naturalIdNumbers.Add(i);
				}

				if ("id".Equals(prop.Name))
				{
					foundNonIdentifierPropertyNamedId = true;
				}

				#region temporary
				bool lazyProperty = prop.IsLazy && lazyAvailable;
				if (lazyProperty)
					hasLazy = true;
				propertyLaziness[i] = lazyProperty;

				propertyNames[i] = properties[i].Name;
				propertyTypes[i] = properties[i].Type;
				propertyNullability[i] = properties[i].IsNullable;
				propertyUpdateability[i] = properties[i].IsUpdateable;
				propertyInsertability[i] = properties[i].IsInsertable;
				insertInclusions[i] = DetermineInsertValueGenerationType(prop, properties[i]);
				updateInclusions[i] = DetermineUpdateValueGenerationType(prop, properties[i]);
				propertyVersionability[i] = properties[i].IsVersionable;
				nonlazyPropertyUpdateability[i] = properties[i].IsUpdateable && !lazyProperty;
				propertyCheckability[i] = propertyUpdateability[i] ||
				                          (propertyTypes[i].IsAssociationType &&
				                           ((IAssociationType) propertyTypes[i]).IsAlwaysDirtyChecked);

				cascadeStyles[i] = properties[i].CascadeStyle;
				#endregion

				if (properties[i].IsLazy)
				{
					hasLazy = true;
				}

				if (properties[i].CascadeStyle != CascadeStyle.None)
				{
					foundCascade = true;
				}

				if (IndicatesCollection(properties[i].Type))
				{
					foundCollection = true;
				}

				if (propertyTypes[i].IsMutable && propertyCheckability[i])
				{
					foundMutable = true;
				}

				if (insertInclusions[i] != ValueInclusion.None)
				{
					foundInsertGeneratedValue = true;
				}

				if (updateInclusions[i] != ValueInclusion.None)
				{
					foundUpdateGeneratedValue = true;
				}

				MapPropertyToIndex(prop, i);
				i++;
			}

			if (naturalIdNumbers.Count == 0)
				naturalIdPropertyNumbers = null;
			else
				naturalIdPropertyNumbers = naturalIdNumbers.ToArray();

			hasCascades = foundCascade;
			hasInsertGeneratedValues = foundInsertGeneratedValue;
			hasUpdateGeneratedValues = foundUpdateGeneratedValue;
			hasNonIdentifierPropertyNamedId = foundNonIdentifierPropertyNamedId;

			versionPropertyIndex = tempVersionProperty;
			hasLazyProperties = hasLazy;
			if (hasLazyProperties) log.Info("lazy property fetching available for: " + name);

			lazy = persistentClass.IsLazy && 
				(!persistentClass.HasPocoRepresentation || !ReflectHelper.IsFinalClass(persistentClass.ProxyInterface));
			mutable = persistentClass.IsMutable;

			if (!persistentClass.IsAbstract.HasValue)
			{
				// legacy behavior (with no abstract attribute specified)
				isAbstract = persistentClass.HasPocoRepresentation &&
				             ReflectHelper.IsAbstractClass(persistentClass.MappedClass);
			}
			else
			{
				isAbstract = persistentClass.IsAbstract.Value;
				if (!isAbstract && persistentClass.HasPocoRepresentation &&
				    ReflectHelper.IsAbstractClass(persistentClass.MappedClass))
				{
					log.Warn("entity [" + type.FullName +
					         "] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names");
				}
			}
			selectBeforeUpdate = persistentClass.SelectBeforeUpdate;
			dynamicUpdate = persistentClass.DynamicUpdate;
			dynamicInsert = persistentClass.DynamicInsert;

			polymorphic = persistentClass.IsPolymorphic;
			explicitPolymorphism = persistentClass.IsExplicitPolymorphism;
			inherited = persistentClass.IsInherited;
			superclass = inherited ? persistentClass.Superclass.EntityName : null;
			superclassType = inherited ?
			                           	persistentClass.Superclass.MappedClass :
			                           	                                       	null;
			hasSubclasses = persistentClass.HasSubclasses;

			optimisticLockMode = persistentClass.OptimisticLockMode;
			if (optimisticLockMode > Versioning.OptimisticLock.Version && !dynamicUpdate)
			{
				throw new MappingException("optimistic-lock setting requires dynamic-update=\"true\": " + type.FullName);
			}

			hasCollections = foundCollection;
			hasMutableProperties = foundMutable;

			foreach (Subclass obj in persistentClass.SubclassIterator)
			{
				subclassEntityNames.Add(obj.EntityName);
			}
			subclassEntityNames.Add(name);

			tuplizerMapping = new EntityEntityModeToTuplizerMapping(persistentClass, this);
		}
Пример #10
0
		public void InitializeEntity(FromClause fromClause,
									string className,
									IEntityPersister persister,
									EntityType type,
									string classAlias,
									string tableAlias)
		{
			DoInitialize(fromClause, tableAlias, className, classAlias, persister, type);
			_initialized = true;
		}
		public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory)
		{
			this.sessionFactory = sessionFactory;


			// TODO H3:
			//name = persistentClass.getEntityName();
			//rootName = persistentClass.getRootClass().getEntityName();
			//entityType = TypeFactory.manyToOne( name );
			type = persistentClass.MappedClass;
			rootType = persistentClass.RootClazz.MappedClass;
			rootTypeAssemblyQualifiedName = rootType.AssemblyQualifiedName;
			entityType = TypeFactory.ManyToOne(type);

			identifierProperty = PropertyFactory.BuildIdentifierProperty(
				persistentClass,
				sessionFactory.GetIdentifierGenerator(rootType)
				);

			versioned = persistentClass.IsVersioned;

			bool lazyAvailable = false;
			// TODO H3:
			//bool lazyAvailable = persistentClass.HasPojoRepresentation &&
			//	typeof(InterceptFieldEnabled).isAssignableFrom( persistentClass.getMappedClass() );
			bool hasLazy = false;

			propertySpan = persistentClass.PropertyClosureSpan;
			properties = new StandardProperty[propertySpan];
			//IList naturalIdNumbers = new ArrayList();

			// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			propertyNames = new string[propertySpan];
			propertyTypes = new IType[propertySpan];
			propertyUpdateability = new bool[propertySpan];
			propertyInsertability = new bool[propertySpan];
			insertInclusions = new ValueInclusion[propertySpan];
			updateInclusions = new ValueInclusion[propertySpan];
			nonlazyPropertyUpdateability = new bool[propertySpan];
			propertyCheckability = new bool[propertySpan];
			propertyNullability = new bool[propertySpan];
			propertyVersionability = new bool[propertySpan];
			propertyLaziness = new bool[propertySpan];
			cascadeStyles = new Cascades.CascadeStyle[propertySpan];
			// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


			int i = 0;
			int tempVersionProperty = NoVersionIndex;
			bool foundCascade = false;
			bool foundCollection = false;
			bool foundMutable = false;
			bool foundInsertGeneratedValue = false;
			bool foundUpdateGeneratedValue = false;

			foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection)
			{
				if (prop == persistentClass.Version)
				{
					tempVersionProperty = i;
					properties[i] = PropertyFactory.BuildVersionProperty(prop, lazyAvailable);
				}
				else
				{
					properties[i] = PropertyFactory.BuildStandardProperty(prop, lazyAvailable);
				}

//				if ( prop.IsNaturalIdentifier ) 
//				{
//					naturalIdNumbers.Add( i );
//				}

				// temporary ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
				// TODO H3:
				//bool lazy = prop.IsLazy && lazyAvailable;
				bool lazyProperty = false;
				if (lazyProperty) hasLazy = true;
				propertyLaziness[i] = lazyProperty;

				propertyNames[i] = properties[i].Name;
				propertyTypes[i] = properties[i].Type;
				propertyNullability[i] = properties[i].IsNullable;
				propertyUpdateability[i] = properties[i].IsUpdateable;
				propertyInsertability[i] = properties[i].IsInsertable;
				insertInclusions[i] = DetermineInsertValueGenerationType(prop, properties[i]);
				updateInclusions[i] = DetermineUpdateValueGenerationType(prop, properties[i]);
				propertyVersionability[i] = properties[i].IsVersionable;
				nonlazyPropertyUpdateability[i] = properties[i].IsUpdateable && !lazyProperty;
				propertyCheckability[i] = propertyUpdateability[i] ||
				                          (propertyTypes[i].IsAssociationType &&
				                           ((IAssociationType) propertyTypes[i]).IsAlwaysDirtyChecked);

				cascadeStyles[i] = properties[i].CascadeStyle;
				// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

				if (properties[i].IsLazy)
				{
					hasLazy = true;
				}

				if (properties[i].CascadeStyle != Cascades.CascadeStyle.StyleNone)
				{
					foundCascade = true;
				}

				if (IndicatesCollection(properties[i].Type))
				{
					foundCollection = true;
				}

				if (propertyTypes[i].IsMutable && propertyCheckability[i])
				{
					foundMutable = true;
				}

				if (insertInclusions[i] != ValueInclusion.None)
				{
					foundInsertGeneratedValue = true;
				}

				if (updateInclusions[i] != ValueInclusion.None)
				{
					foundUpdateGeneratedValue = true;
				}

				MapPropertyToIndex(prop, i);
				i++;
			}

			// TODO H3:
//			if( naturalIdNumbers.Count == 0 )
//			{
//				naturalIdPropertyNumbers = null;
//			}
//			else 
//			{
//				naturalIdPropertyNumbers = ArrayHelper.ToIntArray( naturalIdNumbers );
//			}

			hasCascades = foundCascade;
			hasInsertGeneratedValues = foundInsertGeneratedValue;
			hasUpdateGeneratedValues = foundUpdateGeneratedValue;
			versionPropertyIndex = tempVersionProperty;
			hasLazyProperties = hasLazy;
			if (hasLazyProperties) log.Info("lazy property fetching available for: " + type.FullName);

			lazy = persistentClass.IsLazy;
			// TODO H3:
//			lazy = persistentClass.IsLazy && (
//				// TODO: this disables laziness even in non-pojo entity modes:
//				!persistentClass.HasPojoRepresentation ||
//				!ReflectHelper.IsFinalClass( persistentClass.ProxyInterface )
//				);
			mutable = persistentClass.IsMutable;

			if (persistentClass.IsAbstract == null)
			{
				// legacy behavior (with no abstract attribute specified)
				isAbstract = persistentClass.HasPojoRepresentation &&
				             ReflectHelper.IsAbstractClass(persistentClass.MappedClass);
			}
			else
			{
				isAbstract = (bool) persistentClass.IsAbstract;
				if (!isAbstract && persistentClass.HasPojoRepresentation &&
				    ReflectHelper.IsAbstractClass(persistentClass.MappedClass))
				{
					log.Warn("entity [" + type.FullName +
					         "] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names");
				}
			}
			selectBeforeUpdate = persistentClass.SelectBeforeUpdate;
			dynamicUpdate = persistentClass.DynamicUpdate;
			dynamicInsert = persistentClass.DynamicInsert;

			polymorphic = persistentClass.IsPolymorphic;
			explicitPolymorphism = persistentClass.IsExplicitPolymorphism;
			inherited = persistentClass.IsInherited;
			superclassType = inherited ?
			                 persistentClass.Superclass.MappedClass :
			                 null;
			hasSubclasses = persistentClass.HasSubclasses;

			optimisticLockMode = persistentClass.OptimisticLockMode;
			if (optimisticLockMode > OptimisticLockMode.Version && !dynamicUpdate)
			{
				throw new MappingException("optimistic-lock setting requires dynamic-update=\"true\": " + type.FullName);
			}

			hasCollections = foundCollection;
			hasMutableProperties = foundMutable;

			// TODO H3: tuplizers = TuplizerLookup.create(persistentClass, this);

			foreach (PersistentClass obj in persistentClass.SubclassCollection)
			{
				// TODO H3: subclassEntityNames.Add( obj.EntityName );
				subclassTypes.Add(obj.MappedClass);
			}
			// TODO H3: subclassEntityNames.Add( name );
			subclassTypes.Add(type);
		}
        /// <summary>
        /// Set an association value based on the value of the foreign key.  This updates the property of the entity.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        private void FixupRelationship(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            var entity = entityInfo.Entity;
            if (removeMode)
            {
                meta.SetPropertyValue(entity, propName, null, EntityMode.Poco);
                return;
            }
            object relatedEntity = GetPropertyValue(meta, entity, propName);
            if (relatedEntity != null) return;    // entities are already connected

            relatedEntity = GetRelatedEntity(propName, propType, entityInfo, meta);

            if (relatedEntity != null)
                meta.SetPropertyValue(entity, propName, relatedEntity, EntityMode.Poco);
        }
		private FromElement CreateAndAddFromElement(
				string className,
				string classAlias,
				IEntityPersister entityPersister,
				EntityType type,
				string tableAlias)
		{
			if (!(entityPersister is IJoinable))
			{
				throw new ArgumentException("EntityPersister " + entityPersister + " does not implement Joinable!");
			}

			FromElement element = CreateFromElement(entityPersister);
			InitializeAndAddFromElement(element, className, classAlias, entityPersister, type, tableAlias);
			return element;
		}
		private void InitializeAndAddFromElement(FromElement element,
																						string className,
																						string classAlias,
																						IEntityPersister entityPersister,
																						EntityType type,
																						string tableAlias)
		{
			if (tableAlias == null)
			{
				AliasGenerator aliasGenerator = _fromClause.AliasGenerator;
				tableAlias = aliasGenerator.CreateName(entityPersister.EntityName);
			}
			element.InitializeEntity(_fromClause, className, entityPersister, type, classAlias, tableAlias);
		}
		private FromElement CreateJoin(
						string entityClass,
						string tableAlias,
						JoinSequence joinSequence,
						EntityType type,
						bool manyToMany)
		{
			//  origin, path, implied, columns, classAlias,
			IEntityPersister entityPersister = _fromClause.SessionFactoryHelper.RequireClassPersister(entityClass);
			FromElement destination = CreateAndAddFromElement(entityClass,
							_classAlias,
							entityPersister,
							type,
							tableAlias);
			return InitializeJoin(_path, destination, joinSequence, Columns, _origin, manyToMany);
		}
		private FromElement CreateManyToMany(
						string role,
						string associatedEntityName,
						string roleAlias,
						IEntityPersister entityPersister,
						EntityType type,
						JoinType joinType)
		{
			FromElement elem;
			SessionFactoryHelperExtensions sfh = _fromClause.SessionFactoryHelper;

			if (_inElementsFunction /*implied*/ )
			{
				// For implied many-to-many, just add the end join.
				JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
				elem = CreateJoin(associatedEntityName, roleAlias, joinSequence, type, true);
			}
			else
			{
				// For an explicit many-to-many relationship, add a second join from the intermediate 
				// (many-to-many) table to the destination table.  Also, make sure that the from element's 
				// idea of the destination is the destination table.
				string tableAlias = _fromClause.AliasGenerator.CreateName(entityPersister.EntityName);
				string[] secondJoinColumns = sfh.GetCollectionElementColumns(role, roleAlias);

				// Add the second join, the one that ends in the destination table.
				JoinSequence joinSequence = CreateJoinSequence(roleAlias, joinType);
				joinSequence.AddJoin(sfh.GetElementAssociationType(_collectionType), tableAlias, joinType, secondJoinColumns);
				elem = CreateJoin(associatedEntityName, tableAlias, joinSequence, type, false);
				elem.UseFromFragment = true;
			}
			return elem;
		}
		public FromElement CreateEntityJoin(
				string entityClass,
				string tableAlias,
				JoinSequence joinSequence,
				bool fetchFlag,
				bool inFrom,
				EntityType type)
		{
			FromElement elem = CreateJoin(entityClass, tableAlias, joinSequence, type, false);
			elem.Fetch = fetchFlag;

			//if (numberOfTables > 1 && _implied && !elem.UseFromFragment)
			// NH Different behavior: numberOfTables was removed because an
			// implicit join is an implicit join even if it not come from a
			// multi-table entity
			if (_implied && !elem.UseFromFragment)
			{
				if (Log.IsDebugEnabled)
				{
					Log.Debug("createEntityJoin() : Implied entity join");
				}
				elem.UseFromFragment = true;
			}

			// If this is an implied join in a FROM clause, then use ANSI-style joining, and set the
			// flag on the FromElement that indicates that it was implied in the FROM clause itself.
			if (_implied && inFrom)
			{
				joinSequence.SetUseThetaStyle(false);
				elem.UseFromFragment = true;
				elem.SetImpliedInFromClause(true);
			}
			if (elem.Walker.IsSubQuery)
			{
				// two conditions where we need to transform this to a theta-join syntax:
				//      1) 'elem' is the "root from-element" in correlated subqueries
				//      2) The DotNode.useThetaStyleImplicitJoins has been set to true
				//          and 'elem' represents an implicit join
				if (elem.FromClause != elem.Origin.FromClause || DotNode.UseThetaStyleImplicitJoins)
				{
					// the "root from-element" in correlated subqueries do need this piece
					elem.Type = HqlSqlWalker.FROM_FRAGMENT;
					joinSequence.SetUseThetaStyle(true);
					elem.UseFromFragment = false;
				}
			}

			return elem;
		}
        /// <summary>
        /// Get a related entity based on the value of the foreign key.  Attempts to find the related entity in the
        /// saveMap; if its not found there, it is loaded via the Session (which should create a proxy, not actually load 
        /// the entity from the database).
        /// Related entities are Promoted in the saveOrder according to their state.
        /// </summary>
        /// <param name="propName">Name of the navigation/association property of the entity, e.g. "Customer".  May be null if the property is the entity's identifier.</param>
        /// <param name="propType">Type of the property</param>
        /// <param name="entityInfo">Breeze EntityInfo</param>
        /// <param name="meta">Metadata for the entity class</param>
        /// <returns></returns>
        private object GetRelatedEntity(string propName, EntityType propType, EntityInfo entityInfo, IClassMetadata meta)
        {
            object relatedEntity = null;
            string foreignKeyName = FindForeignKey(propName, meta);
            object id = GetForeignKeyValue(entityInfo, meta, foreignKeyName);

            if (id != null)
            {
                EntityInfo relatedEntityInfo = FindInSaveMap(propType.ReturnedClass, id);

                if (relatedEntityInfo == null) 
                {
                    var state = entityInfo.EntityState;
                    if (state != EntityState.Deleted || !propType.IsNullable)
                    {
                        var relatedEntityName = propType.Name;
                        relatedEntity = session.Load(relatedEntityName, id, LockMode.None);
                    }
                }
                else
                {
                    bool removeReverseRelationship = propType.UseLHSPrimaryKey;
                    AddToGraph(entityInfo, relatedEntityInfo, removeReverseRelationship);
                    relatedEntity = relatedEntityInfo.Entity;
                }
            }
            return relatedEntity;
        }
Пример #19
0
		private void DereferenceEntityJoin(string classAlias, EntityType propertyType, bool impliedJoin, IASTNode parent)
		{
			_dereferenceType = DerefEntity;
			if ( Log.IsDebugEnabled ) 
			{
				Log.Debug( "dereferenceEntityJoin() : generating join for " + _propertyName + " in "
						+ FromElement.ClassName + " "
						+ ( ( classAlias == null ) ? "{no alias}" : "(" + classAlias + ")" )
						+ " parent = " + ASTUtil.GetDebugstring( parent )
				);
			}

			// Create a new FROM node for the referenced class.
			string associatedEntityName = propertyType.GetAssociatedEntityName();
			string tableAlias = AliasGenerator.CreateName( associatedEntityName );

			string[] joinColumns = GetColumns();
			string joinPath = Path;

			if ( impliedJoin && Walker.IsInFrom ) 
			{
				_joinType = Walker.ImpliedJoinType;
			}

			FromClause currentFromClause = Walker.CurrentFromClause;
			FromElement elem = currentFromClause.FindJoinByPath( joinPath );

			///////////////////////////////////////////////////////////////////////////////
			//
			// This is the piece which recognizes the condition where an implicit join path
			// resolved earlier in a correlated subquery is now being referenced in the
			// outer query.  For 3.0final, we just let this generate a second join (which
			// is exactly how the old parser handles this).  Eventually we need to add this
			// logic back in and complete the logic in FromClause.promoteJoin; however,
			// FromClause.promoteJoin has its own difficulties (see the comments in
			// FromClause.promoteJoin).
			//
			//		if ( elem == null ) {
			//			// see if this joinPath has been used in a "child" FromClause, and if so
			//			// promote that element to the outer query
			//			FromClause currentNodeOwner = getFromElement().getFromClause();
			//			FromClause currentJoinOwner = currentNodeOwner.locateChildFromClauseWithJoinByPath( joinPath );
			//			if ( currentJoinOwner != null && currentNodeOwner != currentJoinOwner ) {
			//				elem = currentJoinOwner.findJoinByPathLocal( joinPath );
			//				if ( elem != null ) {
			//					currentFromClause.promoteJoin( elem );
			//					// EARLY EXIT!!!
			//					return;
			//				}
			//			}
			//		}
			//
			///////////////////////////////////////////////////////////////////////////////

			bool found = elem != null;
			// even though we might find a pre-existing element by join path, for FromElements originating in a from-clause
			// we should only ever use the found element if the aliases match (null != null here).  Implied joins are
			// always (?) ok to reuse.
			bool useFoundFromElement = found && ( elem.IsImplied || ( AreSame(classAlias, elem.ClassAlias ) ) );

			if ( ! useFoundFromElement )
			{
				// If this is an implied join in a from element, then use the impled join type which is part of the
				// tree parser's state (set by the gramamar actions).
				JoinSequence joinSequence = SessionFactoryHelper
					.CreateJoinSequence( impliedJoin, propertyType, tableAlias, _joinType, joinColumns );

				FromElementFactory factory = new FromElementFactory(
						currentFromClause,
						GetLhs().FromElement,
						joinPath,
						classAlias,
						joinColumns,
						impliedJoin
				);
				elem = factory.CreateEntityJoin(
						associatedEntityName,
						tableAlias,
						joinSequence,
						_fetch,
						Walker.IsInFrom,
						propertyType
				);
			}
			else 
			{
				currentFromClause.AddDuplicateAlias(classAlias, elem);
			}
		

			SetImpliedJoin( elem );
			Walker.AddQuerySpaces( elem.EntityPersister.QuerySpaces );
			FromElement = elem;	// This 'dot' expression now refers to the resulting from element.
		}
Пример #20
0
		public EntityMetamodel(PersistentClass persistentClass, ISessionFactoryImplementor sessionFactory)
		{
			this.sessionFactory = sessionFactory;


			name = persistentClass.EntityName;
			rootName = persistentClass.RootClazz.EntityName;
			entityType = TypeFactory.ManyToOne(name);
			type = persistentClass.MappedClass;
			rootType = persistentClass.RootClazz.MappedClass;
			rootTypeAssemblyQualifiedName = rootType == null ? null : rootType.AssemblyQualifiedName;

			identifierProperty = PropertyFactory.BuildIdentifierProperty(persistentClass,
			                                                             sessionFactory.GetIdentifierGenerator(rootName));

			versioned = persistentClass.IsVersioned;

			bool lazyAvailable = persistentClass.HasPocoRepresentation
			                     && FieldInterceptionHelper.IsInstrumented(persistentClass.MappedClass);
			bool hasLazy = false;

			propertySpan = persistentClass.PropertyClosureSpan;
			properties = new StandardProperty[propertySpan];
			List<int> naturalIdNumbers = new List<int>();

			propertyNames = new string[propertySpan];
			propertyTypes = new IType[propertySpan];
			propertyUpdateability = new bool[propertySpan];
			propertyInsertability = new bool[propertySpan];
			insertInclusions = new ValueInclusion[propertySpan];
			updateInclusions = new ValueInclusion[propertySpan];
			nonlazyPropertyUpdateability = new bool[propertySpan];
			propertyCheckability = new bool[propertySpan];
			propertyNullability = new bool[propertySpan];
			propertyVersionability = new bool[propertySpan];
			propertyLaziness = new bool[propertySpan];
			cascadeStyles = new CascadeStyle[propertySpan];

			int i = 0;
			int tempVersionProperty = NoVersionIndex;
			bool foundCascade = false;
			bool foundCollection = false;
			bool foundMutable = false;
			bool foundInsertGeneratedValue = false;
			bool foundUpdateGeneratedValue = false;
			bool foundNonIdentifierPropertyNamedId = false;
			HasPocoRepresentation = persistentClass.HasPocoRepresentation;
			
			// NH: WARNING if we have to disable lazy/unproxy properties we have to do it in the whole process.
			lazy = persistentClass.IsLazy && (!persistentClass.HasPocoRepresentation || !ReflectHelper.IsFinalClass(persistentClass.ProxyInterface));
			lazyAvailable &= lazy; // <== Disable lazy properties if the class is marked with lazy=false

			bool hadLazyProperties = false;
			bool hadNoProxyRelations = false;
			foreach (Mapping.Property prop in persistentClass.PropertyClosureIterator)
			{
				if (prop.IsLazy)
				{
					hadLazyProperties = true;
				}
				if(prop.UnwrapProxy)
				{
					hadNoProxyRelations = true;
				}

				// NH: A lazy property is a simple property marked with lazy=true
				bool islazyProperty = prop.IsLazy && lazyAvailable && (!prop.IsEntityRelation || prop.UnwrapProxy);
				// NH: A Relation (in this case many-to-one or one-to-one) marked as "no-proxy"
				var isUnwrapProxy = prop.UnwrapProxy && lazyAvailable;

				if (islazyProperty || isUnwrapProxy)
				{
					// NH: verify property proxiability
					var getter = prop.GetGetter(persistentClass.MappedClass);
					if (getter.Method == null || getter.Method.IsDefined(typeof(CompilerGeneratedAttribute), false) == false)
					{
						log.ErrorFormat("Lazy or no-proxy property {0}.{1} is not an auto property, which may result in uninitialized property access", persistentClass.EntityName, prop.Name);
					}
				}

				if (prop == persistentClass.Version)
				{
					tempVersionProperty = i;
					properties[i] = PropertyFactory.BuildVersionProperty(prop, islazyProperty);
				}
				else
				{
					properties[i] = PropertyFactory.BuildStandardProperty(prop, islazyProperty);
				}

				if (prop.IsNaturalIdentifier)
				{
					naturalIdNumbers.Add(i);
				}

				if ("id".Equals(prop.Name))
				{
					foundNonIdentifierPropertyNamedId = true;
				}

				if (islazyProperty)
				{
					hasLazy = true;
				}
				if (isUnwrapProxy)
				{
					hasUnwrapProxyForProperties = true;
				}

				propertyLaziness[i] = islazyProperty;

				propertyNames[i] = properties[i].Name;
				propertyTypes[i] = properties[i].Type;
				propertyNullability[i] = properties[i].IsNullable;
				propertyUpdateability[i] = properties[i].IsUpdateable;
				propertyInsertability[i] = properties[i].IsInsertable;
				insertInclusions[i] = DetermineInsertValueGenerationType(prop, properties[i]);
				updateInclusions[i] = DetermineUpdateValueGenerationType(prop, properties[i]);
				propertyVersionability[i] = properties[i].IsVersionable;
				nonlazyPropertyUpdateability[i] = properties[i].IsUpdateable && !islazyProperty;
				propertyCheckability[i] = propertyUpdateability[i]
				                          ||
				                          (propertyTypes[i].IsAssociationType
				                           && ((IAssociationType) propertyTypes[i]).IsAlwaysDirtyChecked);

				cascadeStyles[i] = properties[i].CascadeStyle;

				if (properties[i].IsLazy)
				{
					hasLazy = true;
				}

				if (properties[i].CascadeStyle != CascadeStyle.None)
				{
					foundCascade = true;
				}

				if (IndicatesCollection(properties[i].Type))
				{
					foundCollection = true;
				}

				if (propertyTypes[i].IsMutable && propertyCheckability[i])
				{
					foundMutable = true;
				}

				if (insertInclusions[i] != ValueInclusion.None)
				{
					foundInsertGeneratedValue = true;
				}

				if (updateInclusions[i] != ValueInclusion.None)
				{
					foundUpdateGeneratedValue = true;
				}

				MapPropertyToIndex(prop, i);
				i++;
			}

			if (naturalIdNumbers.Count == 0)
				naturalIdPropertyNumbers = null;
			else
				naturalIdPropertyNumbers = naturalIdNumbers.ToArray();

			hasCascades = foundCascade;
			hasInsertGeneratedValues = foundInsertGeneratedValue;
			hasUpdateGeneratedValues = foundUpdateGeneratedValue;
			hasNonIdentifierPropertyNamedId = foundNonIdentifierPropertyNamedId;

			versionPropertyIndex = tempVersionProperty;
			hasLazyProperties = hasLazy;

			if(hadLazyProperties && !hasLazy)
			{
				log.WarnFormat("Disabled lazy properies fetching for {0} beacuse it does not support lazy at the entity level", name);
			}
			if (hasLazy)
			{
				log.Info("lazy property fetching available for: " + name);
			}

			if(hadNoProxyRelations && !hasUnwrapProxyForProperties)
			{
				log.WarnFormat("Disabled ghost properies fetching for {0} beacuse it does not support lazy at the entity level", name);
			}
			if (hasUnwrapProxyForProperties)
			{
				log.Info("no-proxy property fetching available for: " + name);
			}

			mutable = persistentClass.IsMutable;

			if (!persistentClass.IsAbstract.HasValue)
			{
				// legacy behavior (with no abstract attribute specified)
				isAbstract = persistentClass.HasPocoRepresentation && ReflectHelper.IsAbstractClass(persistentClass.MappedClass);
			}
			else
			{
				isAbstract = persistentClass.IsAbstract.Value;
				if (!isAbstract && persistentClass.HasPocoRepresentation
				    && ReflectHelper.IsAbstractClass(persistentClass.MappedClass))
				{
					log.Warn("entity [" + type.FullName
					         + "] is abstract-class/interface explicitly mapped as non-abstract; be sure to supply entity-names");
				}
			}
			selectBeforeUpdate = persistentClass.SelectBeforeUpdate;
			dynamicUpdate = persistentClass.DynamicUpdate;
			dynamicInsert = persistentClass.DynamicInsert;

			polymorphic = persistentClass.IsPolymorphic;
			explicitPolymorphism = persistentClass.IsExplicitPolymorphism;
			inherited = persistentClass.IsInherited;
			superclass = inherited ? persistentClass.Superclass.EntityName : null;
			superclassType = inherited ? persistentClass.Superclass.MappedClass : null;
			hasSubclasses = persistentClass.HasSubclasses;

			optimisticLockMode = persistentClass.OptimisticLockMode;
			if (optimisticLockMode > Versioning.OptimisticLock.Version && !dynamicUpdate)
			{
				throw new MappingException("optimistic-lock setting requires dynamic-update=\"true\": " + type.FullName);
			}

			hasCollections = foundCollection;
			hasMutableProperties = foundMutable;

			foreach (Subclass obj in persistentClass.SubclassIterator)
			{
				subclassEntityNames.Add(obj.EntityName);
			}
			subclassEntityNames.Add(name);

			tuplizerMapping = new EntityEntityModeToTuplizerMapping(persistentClass, this);
		}
Пример #21
0
		/// <summary>
		/// Is the given property name a reference to the primary key of the associated
		/// entity construed by the given entity type?
		/// For example, consider a fragment like order.customer.id
		/// (where order is a from-element alias).  Here, we'd have:
		/// propertyName = "id" AND
		/// owningType = ManyToOneType(Customer)
		/// and are being asked to determine whether "customer.id" is a reference
		/// to customer's PK...
		/// </summary>
		/// <param name="propertyName">The name of the property to check.</param>
		/// <param name="owningType">The type represeting the entity "owning" the property</param>
		/// <returns>True if propertyName references the entity's (owningType->associatedEntity) primary key; false otherwise.</returns>
		private bool IsReferenceToPrimaryKey(string propertyName, EntityType owningType)
		{
			IEntityPersister persister = SessionFactoryHelper.Factory.GetEntityPersister(owningType.GetAssociatedEntityName());
			if (persister.EntityMetamodel.HasNonIdentifierPropertyNamedId)
			{
				// only the identifier property field name can be a reference to the associated entity's PK...
				return propertyName == persister.IdentifierPropertyName && owningType.IsReferenceToPrimaryKey;
			}
			
			// here, we have two possibilities:
			// 		1) the property-name matches the explicitly identifier property name
			//		2) the property-name matches the implicit 'id' property name
			if (EntityPersister.EntityID == propertyName)
			{
				// the referenced node text is the special 'id'
				return owningType.IsReferenceToPrimaryKey;
			}
			
			string keyPropertyName = SessionFactoryHelper.GetIdentifierOrUniqueKeyPropertyName(owningType);
			return keyPropertyName != null && keyPropertyName == propertyName && owningType.IsReferenceToPrimaryKey;
		}
Пример #22
0
		private void DoInitialize(FromClause fromClause, string tableAlias, string className, string classAlias,
								  IEntityPersister persister, EntityType type)
		{
			if (_initialized)
			{
				throw new InvalidOperationException("Already initialized!!");
			}
			_fromClause = fromClause;
			_tableAlias = tableAlias;
			_className = className;
			_classAlias = classAlias;
			_elementType = new FromElementType(this, persister, type);

			// Register the FromElement with the FROM clause, now that we have the names and aliases.
			fromClause.RegisterFromElement(this);

			if (Log.IsDebugEnabled)
			{
				Log.Debug(fromClause + " :  " + className + " ("
						+ (classAlias ?? "no alias") + ") -> " + tableAlias);
			}
		}
		/// <summary>
		/// Determine the name of the property for the entity encapsulated by the
		/// given type which represents the id or unique-key.
		/// </summary>
		/// <param name="entityType">The type representing the entity.</param>
		/// <returns>The corresponding property name</returns>
		public string GetIdentifierOrUniqueKeyPropertyName(EntityType entityType)
		{
			try
			{
				return entityType.GetIdentifierOrUniqueKeyPropertyName(_sfi);
			}
			catch (MappingException me)
			{
				throw new QueryException(me);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="propertyName"></param>
		/// <param name="propertyType"></param>
		/// <param name="q"></param>
		/// <remarks>NOTE: we avoid joining to the next table if the named property is just the foreign key value</remarks>
		private void DereferenceEntity(string propertyName, EntityType propertyType, QueryTranslator q)
		{
			//if its "id"
			bool isIdShortcut = EntityID.Equals(propertyName) && !propertyType.IsUniqueKeyReference;

			//or its the id property name
			string idPropertyName;
			try
			{
				idPropertyName = propertyType.GetIdentifierOrUniqueKeyPropertyName(q.Factory);
			}
			catch (MappingException me)
			{
				throw new QueryException(me);
			}
			bool isNamedIdPropertyShortcut = idPropertyName != null && idPropertyName.Equals(propertyName);

			if (isIdShortcut || isNamedIdPropertyShortcut)
			{
				// special shortcut for id properties, skip the join!
				// this must only occur at the _end_ of a path expression
				DereferenceProperty(propertyName);
			}
			else
			{
				string entityClass = propertyType.GetAssociatedEntityName();
				string name = q.CreateNameFor(entityClass);
				q.AddType(name, entityClass);
				//String[] keyColNames = memberPersister.getIdentifierColumnNames();
				AddJoin(name, propertyType);
                if (propertyType.IsOneToOne)
                {
                    oneToOneOwnerName = currentName;
                }
                else
                {
                    oneToOneOwnerName = null;
                }
				ownerAssociationType = propertyType;
				currentName = name;
				currentProperty = propertyName;
				q.AddPathAliasAndJoin(path.ToString(0, path.ToString().LastIndexOf(StringHelper.Dot)), name, joinSequence.Copy());
				componentPath.Length = 0;
				currentPropertyMapping = q.GetPersister(entityClass);
			}
		}
		/// <summary>
		///  Visit a many-to-one or one-to-one associated entity. Default superclass implementation is a no-op.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="entityType"></param>
		/// <returns></returns>
		internal virtual object ProcessEntity(object value, EntityType entityType)
		{
			return null;
		}
		private bool HasNonIdentifierPropertyNamedId(EntityType entityType, IMapping factory)
		{
			// NH: Different implementation (removed done "todo" of H3.2.6)
			return factory.HasNonIdentifierPropertyNamedId(entityType.GetAssociatedEntityName());
		}
		/// <summary>
		/// Visit a many-to-one or one-to-one associated entity. Default
		/// superclass implementation is a no-op.
		/// </summary>
		/// <param name="value"></param>
		/// <param name="entityType"></param>
		/// <returns></returns>
		protected virtual object ProcessEntity(object value, EntityType entityType)
		{
			return null;
		}