Ejemplo n.º 1
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 property fetching for {0} because 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 property fetching for {0} because 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);

            EntityMode = persistentClass.HasPocoRepresentation ? EntityMode.Poco : EntityMode.Map;

            var entityTuplizerFactory = new EntityTuplizerFactory();
            var tuplizerClassName     = persistentClass.GetTuplizerImplClassName(EntityMode);

            Tuplizer = tuplizerClassName == null
                                ? entityTuplizerFactory.BuildDefaultEntityTuplizer(EntityMode, this, persistentClass)
                                : entityTuplizerFactory.BuildEntityTuplizer(tuplizerClassName, this, persistentClass);
        }