📄 entitymetamodel.cs
字号:
using System;
using System.Collections.Generic;
using Iesi.Collections.Generic;
using log4net;
using NHibernate.Engine;
using NHibernate.Intercept;
using NHibernate.Mapping;
using NHibernate.Type;
using NHibernate.Util;
namespace NHibernate.Tuple.Entity
{
[Serializable]
public class EntityMetamodel
{
private static readonly ILog log = LogManager.GetLogger(typeof(EntityMetamodel));
private const int NoVersionIndex = -66;
private readonly ISessionFactoryImplementor sessionFactory;
private readonly string name;
private readonly string rootName;
private readonly System.Type type;
private readonly System.Type rootType;
private readonly string rootTypeAssemblyQualifiedName;
private readonly EntityType entityType;
private readonly IdentifierProperty identifierProperty;
private readonly bool versioned;
private readonly int propertySpan;
private readonly int versionPropertyIndex;
private readonly StandardProperty[] properties;
#region temporary
private readonly string[] propertyNames;
private readonly IType[] propertyTypes;
private readonly bool[] propertyLaziness;
private readonly bool[] propertyUpdateability;
private readonly bool[] nonlazyPropertyUpdateability;
private readonly bool[] propertyCheckability;
private readonly bool[] propertyInsertability;
private readonly ValueInclusion[] insertInclusions;
private readonly ValueInclusion[] updateInclusions;
private readonly bool[] propertyNullability;
private readonly bool[] propertyVersionability;
private readonly CascadeStyle[] cascadeStyles;
#endregion
private readonly IDictionary<string, int?> propertyIndexes = new Dictionary<string, int?>();
private readonly bool hasCollections;
private readonly bool hasMutableProperties;
private readonly bool hasLazyProperties;
private readonly int[] naturalIdPropertyNumbers;
private bool lazy;
private readonly bool hasCascades;
private readonly bool hasNonIdentifierPropertyNamedId;
private readonly bool mutable;
private readonly bool isAbstract;
private readonly bool selectBeforeUpdate;
private readonly bool dynamicUpdate;
private readonly bool dynamicInsert;
private readonly Versioning.OptimisticLock optimisticLockMode;
private readonly bool polymorphic;
private readonly string superclass;
private readonly System.Type superclassType;
private readonly bool explicitPolymorphism;
private readonly bool inherited;
private readonly bool hasSubclasses;
private readonly HashedSet<string> subclassEntityNames = new HashedSet<string>();
private readonly bool hasInsertGeneratedValues;
private readonly bool hasUpdateGeneratedValues;
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);
}
private ValueInclusion DetermineInsertValueGenerationType(Mapping.Property mappingProperty, StandardProperty runtimeProperty)
{
if (runtimeProperty.IsInsertGenerated)
{
return ValueInclusion.Full;
}
else if (mappingProperty.Value is Mapping.Component)
{
if (HasPartialInsertComponentGeneration((Mapping.Component)mappingProperty.Value))
{
return ValueInclusion.Partial;
}
}
return ValueInclusion.None;
}
private bool HasPartialInsertComponentGeneration(Mapping.Component component)
{
foreach (Mapping.Property prop in component.PropertyIterator)
{
if (prop.Generation == PropertyGeneration.Always || prop.Generation == PropertyGeneration.Insert)
{
return true;
}
else if (prop.Value is Mapping.Component)
{
if (HasPartialInsertComponentGeneration((Mapping.Component)prop.Value))
{
return true;
}
}
}
return false;
}
private ValueInclusion DetermineUpdateValueGenerationType(Mapping.Property mappingProperty, StandardProperty runtimeProperty)
{
if (runtimeProperty.IsUpdateGenerated)
{
return ValueInclusion.Full;
}
else if (mappingProperty.Value is Mapping.Component)
{
if (HasPartialUpdateComponentGeneration((Mapping.Component)mappingProperty.Value))
{
return ValueInclusion.Partial;
}
}
return ValueInclusion.None;
}
private bool HasPartialUpdateComponentGeneration(Mapping.Component component)
{
foreach (Mapping.Property prop in component.PropertyIterator)
{
if (prop.Generation == PropertyGeneration.Always)
{
return true;
}
else if (prop.Value is Mapping.Component)
{
if (HasPartialUpdateComponentGeneration((Mapping.Component)prop.Value))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -