private async Task UpdateEntityAssociationAsync( EntityAssociation association, EntityInfo entityInfo, AbstractEntityPersister persister, EntityIdMap entitiesIdMap, DependencyGraph dependencyGraph, ConfiguredSessionProvider sessionProvider, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); var dbEntity = entityInfo.Entity; var originalFkValue = await(GetClientForeignKeyValueAsync(association, entityInfo, entitiesIdMap, true, sessionProvider, cancellationToken)).ConfigureAwait(false); TryAddToGraphAndUpdateParent(entityInfo, entitiesIdMap, dependencyGraph, originalFkValue, association, true, true, sessionProvider, out _); var newFkValue = await(GetClientForeignKeyValueAsync(association, entityInfo, entitiesIdMap, false, sessionProvider, cancellationToken)).ConfigureAwait(false); TryAddToGraphAndUpdateParent(entityInfo, entitiesIdMap, dependencyGraph, newFkValue, association, false, true, sessionProvider, out var parentEntityInfo); // Set the entity association (e.g. Order = value) var associatedEntity = newFkValue != null ? parentEntityInfo?.Entity ?? await(LoadEntityAsync(association.EntityType, newFkValue, sessionProvider, cancellationToken)).ConfigureAwait(false) : null; persister.SetPropertyValue( dbEntity, persister.GetPropertyIndex(association.AssociationPropertyName), associatedEntity); }
/// <summary> /// Find a join. Return the name of the corresponding property. /// </summary> private static AbstractEntityPersister FindJoinedEntity(SessionFactoryImpl sf, AbstractEntityPersister root, string toTable, string fromField, out string propertyName) { // root.ClassMetadata.PropertyTypes.First().Na for (int i = 0; i < root.PropertyTypes.Length; i++) { if (root.PropertyTypes[i].IsAssociationType && !root.PropertyTypes[i].IsCollectionType) { String[] cols = root.ToColumns(root.PropertyNames[i]); if (cols.Length == 1 && cols[0] == fromField) { propertyName = root.PropertyNames[i]; Type t = root.PropertyTypes[i].ReturnedClass; String entityName = sf.TryGetGuessEntityName(t); AbstractEntityPersister persister = (AbstractEntityPersister)sf.GetEntityPersister(entityName); if (persister.TableName == toTable) { return(persister); } // special case for acct mgr if (toTable == "USERINFO" && persister.TableName == "USERSECURITY") { propertyName = propertyName + ".UserInfo"; entityName = "Sage.SalesLogix.Security.UserInfo"; return((AbstractEntityPersister)sf.GetEntityPersister(entityName)); } } } } propertyName = null; return(null); }
/// <summary> /// Return names of all properties that are defined in the mapped ancestors of the /// given persister. Note that unmapped superclasses are deliberately ignored, because /// they shouldn't affect the metadata. /// </summary> /// <param name="persister"></param> /// <returns>set of property names. Empty if the persister doesn't have a superclass.</returns> HashSet <string> GetSuperProperties(AbstractEntityPersister persister) { HashSet <string> set = new HashSet <String>(); if (!persister.IsInherited) { return(set); } string superClassName = persister.MappedSuperclass; if (superClassName == null) { return(set); } IClassMetadata superMeta = _sessionFactory.GetClassMetadata(superClassName); if (superMeta == null) { return(set); } string[] superProps = superMeta.PropertyNames; set = new HashSet <string>(superProps); set.Add(superMeta.IdentifierPropertyName); return(set); }
public Boolean DeleteAll() { AbstractEntityPersister metadata = HibernateHelper.SessionFactory.GetClassMetadata(typeof(T)) as NHibernate.Persister.Entity.AbstractEntityPersister; String table = metadata.TableName; using (ISession session = HibernateHelper.OpenSession()) { using (ITransaction transaction = session.BeginTransaction()) { try { string deleteAll = String.Format("Delete From \"{0}\"", table); session.CreateSQLQuery(deleteAll).ExecuteUpdate(); transaction.Commit(); return(true); } catch (Exception) { transaction.Rollback(); return(false); } finally { session.Disconnect(); session.Close(); } } } }
public static string GetTableName <T>( ) { IClassMetadata md = Connection.Database.Instance.SessionFactory.GetClassMetadata(typeof(T)); AbstractEntityPersister aep = md as AbstractEntityPersister; return(aep.TableName); //return new NHibernate.Cfg.Configuration().GetClassMapping(typeof(T)).RootTable.Name; }
public EntityBatchFetcher(AbstractEntityPersister persister) { _parameter = Expression.Parameter(typeof(TEntity)); var property = Expression.Property(_parameter, persister.IdentifierPropertyName); _idExpression = Expression.Lambda <Func <TEntity, TId> >(property, _parameter); _idSelector = Expression.Lambda <Func <TEntity, object> >(Expression.Convert(property, typeof(object)), _parameter).Compile(); _containsMethod = ReflectHelper.GetMethod(() => Enumerable.Contains(null, default(TId))); }
/// <summary> /// Attempt to extract properties from the lookup metadata. /// The result of this operation is cached. /// </summary> /// <param name="lookupName"></param> /// <param name="entityTypeName"></param> /// <returns></returns> internal static LookupPropertyCollection GetLookupProperties(String lookupName, String entityTypeName) { LookupPropertyCollection result = null; if (HttpContext.Current != null && ((result = HttpContext.Current.Cache["LookupProperties$" + entityTypeName + "$" + lookupName] as LookupPropertyCollection) != null)) { return(result); } result = new LookupPropertyCollection(); using (var sess = new SessionScopeWrapper()) { Type entityType = Type.GetType(entityTypeName); if (entityType == null) { throw new ArgumentException("Unable to locate type " + entityTypeName); } if (entityType.IsInterface) { throw new ArgumentException("Must use the concrete class as EntityTypeName (e.g., Sage.SalesLogix.Entities.Contact)"); } String entityName = ((SessionFactoryImpl)sess.SessionFactory).TryGetGuessEntityName(entityType); if (entityName == null) { throw new ArgumentException("Unable to locate persister for entity type " + entityType.FullName); } AbstractEntityPersister persister = (AbstractEntityPersister)((SessionFactoryImpl)sess.SessionFactory).GetEntityPersister(entityName); foreach (LookupLayoutField lookupField in GetLookupFields(sess, persister.TableName, lookupName)) { String[] tableField = lookupField.Path.Split(new char[] { ':' }); if (persister == null || persister.TableName != tableField[0]) { throw new ArgumentException("Invalid lookup data - table name does not match persister table (" + persister.TableName + " vs " + tableField[0] + ") - check EntityName setting"); } String propName = DecomposePath((SessionFactoryImpl)sess.SessionFactory, persister, tableField[1], lookupField.Format); if (propName != null) { result.Add(new LookupProperty(propName, lookupField.Caption)); // TODO: we should set the property format here } } } if (LOG.IsDebugEnabled) { foreach (LookupProperty prop in result) { LOG.Debug("Using property '" + prop.PropertyName + "' with header '" + prop.PropertyHeader + "'"); } } if (HttpContext.Current != null) { HttpContext.Current.Cache["LookupProperties$" + entityTypeName + "$" + lookupName] = result; } return(result); }
public void TestFormatOwner() { String entityName = "Sage.SalesLogix.Entities.Contact"; using (var sess = new SessionScopeWrapper()) { SessionFactoryImpl sf = (SessionFactoryImpl)sess.SessionFactory; AbstractEntityPersister persister = (AbstractEntityPersister)(sf.GetEntityPersister(entityName)); Assert.AreEqual("Owner.OwnerDescription", SimpleLookup.DecomposePath(sf, persister, "SECCODEID", "8")); } }
public override string GetAuditNoteForComponentProperty(AbstractEntityPersister persister, ComponentType componentType, int propertyIndexToAudit) { string componentPropertyName = persister.PropertyNames[propertyIndexToAudit]; object oldComponentValue = _oldStates[propertyIndexToAudit]; object newComponentValue = _newStates[propertyIndexToAudit]; string note = GetAuditNoteForComponent(persister, componentType, componentPropertyName, new UpdateComponentAuditStrategy(oldComponentValue, newComponentValue)); return(note); }
public void TestFormatUserName() { String entityName = "Sage.SalesLogix.Entities.Contact"; using (var sess = new SessionScopeWrapper()) { SessionFactoryImpl sf = (SessionFactoryImpl)sess.SessionFactory; AbstractEntityPersister persister = (AbstractEntityPersister)(sf.GetEntityPersister(entityName)); Assert.AreEqual("AccountManager.UserInfo.UserName", SimpleLookup.DecomposePath(sf, persister, "ACCOUNTMANAGERID", "6")); } }
private void AddIdentifierProperties( AbstractEntityPersister persister, EntityType entityType, ModelConfiguration modelConfiguration, EntityMetadata entityMetadata, BreezeMetadata metadata) { // Add the identifier properties only for the root class if (persister.IsInherited) { return; } if (persister.HasIdentifierProperty) { var memberConfiguration = modelConfiguration.GetMember(persister.IdentifierPropertyName); var dataProperty = CreateDataProperty( persister.IdentifierPropertyName, persister.IdentifierType, true, false, false, memberConfiguration, entityType, persister.Factory); entityType.DataProperties.Insert(0, dataProperty); } else if (persister.IdentifierType is IAbstractComponentType componentType) { modelConfiguration = _breezeConfigurator.GetModelConfiguration(componentType.ReturnedClass); AddDataProperties( componentType.PropertyNames, componentType.Subtypes, componentType.PropertyNullability, null, null, true, entityType, modelConfiguration, metadata, persister.Factory); AddAssociationProperties( componentType.PropertyNames, componentType.Subtypes, true, i => componentType.GetCascadeStyle(i), entityType, null, modelConfiguration, entityMetadata); } }
/// <summary> /// Path represents path to a field, based at origin. /// Return the field object. /// A field path is normally of the form: /// Source Table:Path /// where Path is recursively defined as either: /// FieldName /// or /// From Field=To Field.To Table!Path /// </summary> /// <param name="sf"></param> /// <param name="root"></param> /// <param name="path"></param> /// <param name="format"></param> internal static String DecomposePath(SessionFactoryImpl sf, AbstractEntityPersister root, String path, String format) { String[] parts; parts = path.Split(new char[] { '!' }, 2); if (parts.Length == 1) { // field name // remove initial "@" (this is used to indicate calculated fields) if (parts[0][0] == '@') { parts[0] = parts[0].Substring(1); } String fieldName = parts[0].ToUpper(); for (int i = 0; i < root.PropertyTypes.Length; i++) { IType propType = root.PropertyTypes[i]; if (propType.IsCollectionType) { continue; } String propName = root.PropertyNames[i]; String[] columns = root.ToColumns(propName); if (columns.Length == 1 && columns[0].ToUpper() == fieldName) { return(FormatProperty(propName, propType, format)); } } LOG.Warn("Unable to locate property by column - " + parts[0]); return(null); } else { String newpath = parts[1]; // part after the exclamation mark Match matches = _fieldPathRegexp.Match(parts[0]); if (!matches.Success) { throw new ArgumentException("Path did not match field expression pattern: " + parts[0]); } System.Diagnostics.Debug.Assert(matches.Groups.Count == 5, "Number of Groups should have been 5, was " + matches.Groups.Count + " (path = " + parts[0] + ")"); String toTable = matches.Groups[4].Value; String fromField = matches.Groups[1].Value; String propertyName; root = FindJoinedEntity(sf, root, toTable, fromField, out propertyName); if (root == null) { throw new ArgumentException("Unable to locate linked property " + toTable + " via " + fromField + "!"); } return(propertyName + "." + DecomposePath(sf, root, newpath, format)); } }
// e.g. componentPropertyNameChain = "Name.First" for patient first name internal string GetAuditNoteForComponent(AbstractEntityPersister persister, ComponentType componentType, string componentPropertyNameChain, IComponentAuditStrategy propertyAuditStrategy) { var noteBulder = new StringBuilder(); Type componentDotNetType = componentType.ReturnedClass; foreach (PropertyInfo propertyInfo in componentDotNetType.GetProperties()) { if (propertyAuditStrategy.IsExcludedFromAudit(propertyInfo)) { continue; } var ignoreMappingTypeAttributes = propertyInfo.GetCustomAttributes(typeof(IgnoreMappingAttribute), false); if (ignoreMappingTypeAttributes.Length != 0) { continue; } string propertyName = propertyInfo.Name; var wholeComponentPropertyNameChain = string.Format("{0}.{1}", componentPropertyNameChain, propertyName); var subComponentType = componentType.Subtypes.FirstOrDefault(p => p.ReturnedClass.FullName == propertyInfo.PropertyType.FullName && p.IsComponentType) as ComponentType; string note; if (subComponentType == null) { string columnName = string.Join(",", persister.GetPropertyColumnNames(wholeComponentPropertyNameChain)); note = propertyAuditStrategy.GetAuditNoteForNonComponentProperty(propertyInfo, columnName); } else { note = GetAuditNoteForComponent( persister, subComponentType, wholeComponentPropertyNameChain, propertyAuditStrategy.GetComponentPropertyAuditStrategy(propertyInfo)); } if (!string.IsNullOrWhiteSpace(note)) { noteBulder.AppendLine(); } } return(noteBulder.ToString().Trim()); }
/// <summary> /// Initialize and configure the data source using given properties. /// Called when space is started. /// </summary> /// <param name="properties">Propeties to initialize by.</param> public override void Init(Dictionary <string, string> properties) { base.Init(properties); _enumeratorLoadFetchSize = GetIntProperty("EnumeratorLoadFetchSize", _enumeratorLoadFetchSize); _initialLoadChunkSize = GetIntProperty("InitialLoadChunkSize", _initialLoadChunkSize); _performOrderById = GetBoolProperty("PerformOrderById", _performOrderById); _initialLoadThreadPoolSize = GetIntProperty("InitialLoadThreadPoolSize", _initialLoadThreadPoolSize); _useMerge = GetBoolProperty("UseMerge", _useMerge); // only configure a session factory if it is not injected if (_sessionFactory == null) { string nhibernateFile = GetFileProperty(NHibernateConfigProperty); string hbmDirectory = GetFileProperty(NHibernateHbmDirectory); string connectionString = GetProperty(NHibernateConnectionStringProperty); _sessionFactory = SessionFactoryBuilder.GetFactory(nhibernateFile, hbmDirectory, connectionString); } // only extract managed entries if it wasn't injected if (_managedEntries == null) { List <string> managedEntriesList = new List <string>(); IDictionary <string, IClassMetadata> allClassMetadata = _sessionFactory.GetAllClassMetadata(); foreach (string type in allClassMetadata.Keys) { managedEntriesList.Add(type); } ManagedEntries = managedEntriesList.ToArray(); } // only extract initial load entries if it wasn't injected if (_initialLoadEntries == null) { List <string> initialLoadEntriesList = new List <string>(); IDictionary <string, IClassMetadata> allClassMetadata = _sessionFactory.GetAllClassMetadata(); foreach (KeyValuePair <string, IClassMetadata> entry in allClassMetadata) { AbstractEntityPersister entityPersister = (AbstractEntityPersister)entry.Value; string mappedSuperClass = entityPersister.MappedSuperclass; if (mappedSuperClass != null) { IClassMetadata superClassMetadata = allClassMetadata[mappedSuperClass]; if (superClassMetadata.GetMappedClass(EntityMode.Map) != null) { //Filter out those who have their super classes mapped continue; } } initialLoadEntriesList.Add(entry.Key); } InitialLoadEntries = initialLoadEntriesList.ToArray(); } }
public void TestDecomposePath() { String entityName = "Sage.SalesLogix.Entities.Contact"; using (var sess = new SessionScopeWrapper()) { SessionFactoryImpl sf = (SessionFactoryImpl)sess.SessionFactory; AbstractEntityPersister persister = (AbstractEntityPersister)(sf.GetEntityPersister(entityName)); Assert.AreEqual("LastName", SimpleLookup.DecomposePath(sf, persister, "LASTNAME", "0")); Assert.AreEqual("Address.PostalCode", SimpleLookup.DecomposePath(sf, persister, "ADDRESSID=ADDRESSID.ADDRESS!POSTALCODE", "0")); Assert.AreEqual("AccountManager.UserInfo.UserName", SimpleLookup.DecomposePath(sf, persister, "ACCOUNTMANAGERID>USERID.USERINFO!USERNAME", "0")); } }
private SqlString GenerateSequentialSelect(ILoadable persister) { //note that this method could easily be moved up to BasicEntityPersister, //if we ever needed to reuse it from other subclasses //figure out which tables need to be fetched AbstractEntityPersister subclassPersister = (AbstractEntityPersister)persister; HashedSet <int> tableNumbers = new HashedSet <int>(); string[] props = subclassPersister.PropertyNames; string[] classes = subclassPersister.PropertySubclassNames; for (int i = 0; i < props.Length; i++) { int propTableNumber = GetSubclassPropertyTableNumber(props[i], classes[i]); if (IsSubclassTableSequentialSelect(propTableNumber) && !IsSubclassTableLazy(propTableNumber)) { tableNumbers.Add(propTableNumber); } } if ((tableNumbers.Count == 0)) { return(null); } //figure out which columns are needed List <int> columnNumbers = new List <int>(); int[] columnTableNumbers = SubclassColumnTableNumberClosure; for (int i = 0; i < SubclassColumnClosure.Length; i++) { if (tableNumbers.Contains(columnTableNumbers[i])) { columnNumbers.Add(i); } } //figure out which formulas are needed List <int> formulaNumbers = new List <int>(); int[] formulaTableNumbers = SubclassColumnTableNumberClosure; for (int i = 0; i < SubclassFormulaTemplateClosure.Length; i++) { if (tableNumbers.Contains(formulaTableNumbers[i])) { formulaNumbers.Add(i); } } //render the SQL return(RenderSelect(ArrayHelper.ToIntArray(tableNumbers), columnNumbers.ToArray(), formulaNumbers.ToArray())); }
/// <summary> /// Constructs an instance of <see cref="EntityMetadata"/>. /// </summary> public EntityMetadata( AbstractEntityPersister entityPersister, Func <object> createInstance, IEntityBatchFetcher batchFetcher, Type type, Type baseType, AutoGeneratedKeyType autoGeneratedKeyType, string versionPropertyName, Type versionPropertyType, bool hasCompositeKey, IReadOnlyDictionary <string, SyntheticForeignKeyProperty> syntheticForeignKeyProperties, IReadOnlyCollection <Type> derivedTypes, IReadOnlyCollection <string> derivedPropertyNames, IReadOnlyList <string> identifierPropertyNames, IReadOnlyList <Func <object, object> > identifierPropertyGetters, IReadOnlyList <Type> identifierPropertyTypes, IReadOnlyList <DataType> identifierPropertyDataTypes, IReadOnlyList <int?> identifierPropertyTypeLengths, IReadOnlyCollection <string> foreignKeyPropertyNames, IReadOnlyDictionary <string, Association> associations, IReadOnlyDictionary <string, EntityAssociation> foreignKeyAssociations, IReadOnlyDictionary <string, Func <object, object> > manyToOneIdentifierProperties) : base( type, baseType, autoGeneratedKeyType, hasCompositeKey, syntheticForeignKeyProperties, derivedTypes, derivedPropertyNames, identifierPropertyNames, identifierPropertyGetters, identifierPropertyTypes, identifierPropertyDataTypes, identifierPropertyTypeLengths, foreignKeyPropertyNames, associations) { EntityPersister = entityPersister; CreateInstance = createInstance; BatchFetcher = batchFetcher; ForeignKeyAssociations = foreignKeyAssociations; VersionPropertyName = versionPropertyName; VersionPropertyType = versionPropertyType; ManyToOneIdentifierProperties = manyToOneIdentifierProperties; AllProperties = new HashSet <string>( identifierPropertyNames .Concat(manyToOneIdentifierProperties.Keys) // We have to add also many-to-one identifier names as identifierPropertyNames does not contain them .Concat(entityPersister.PropertyNames) .Concat(syntheticForeignKeyProperties.Select(o => o.Key))); }
public override string GetAuditNoteForComponentProperty(AbstractEntityPersister persister, ComponentType componentType, int propertyIndexToAudit) { string componentPropertyName = persister.PropertyNames[propertyIndexToAudit]; object componentValue = _states[propertyIndexToAudit]; string note = string.Empty; if (componentValue != null) { note = GetAuditNoteForComponent(persister, componentType, componentPropertyName, new DefaultComponentAuditStrategy(componentValue)); } return(note); }
/// <summary> /// Render a SqlString for the expression. /// </summary> /// <param name="criteria"></param> /// <param name="criteriaQuery"></param> /// <param name="enabledFilters"></param> /// <returns> /// A SqlString that contains a valid Sql fragment. /// </returns> public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery, IDictionary <string, IFilter> enabledFilters) { IEnumerable <Parameter> parameters = criteriaQuery.NewQueryParameter(GetParameterTypedValue(criteria, criteriaQuery)); Parameter p = null; foreach (Parameter p_ in parameters) { p = p_; } //Parameter[] p = criteriaQuery.NewQueryParameter(GetTypedValues(criteria, criteriaQuery)[0]).ToArray(); ISpatialDialect spatialDialect = (ISpatialDialect)criteriaQuery.Factory.Dialect; string[] columnsUsingProjection = criteriaQuery.GetColumnsUsingProjection(criteria, this.propertyName); IType typeUsingProjection = criteriaQuery.GetTypeUsingProjection(criteria, this.propertyName); if (typeUsingProjection.IsCollectionType) { throw new QueryException(string.Format("cannot use collection property ({0}.{1}) directly in a criterion, use ICriteria.CreateCriteria instead", criteriaQuery.GetEntityName(criteria), this.propertyName)); } string[] keyColumns = criteriaQuery.GetIdentifierColumns(criteria); string entityType = criteriaQuery.GetEntityName(criteria, this.propertyName); AbstractEntityPersister entityPersister = (AbstractEntityPersister)criteriaQuery.Factory.GetEntityPersister(entityType); // Only one key column is assumed string keyColumn = keyColumns[0]; string alias = criteriaQuery.GetSQLAlias(criteria, this.propertyName); string tableName = entityPersister.TableName; int aliasLength = alias.Length + 1; SqlStringBuilder builder = new SqlStringBuilder(10 * columnsUsingProjection.Length); for (int i = 0; i < columnsUsingProjection.Length; i++) { if (i > 0) { builder.Add(" AND "); } string geometryColumn = columnsUsingProjection[i].Remove(0, aliasLength); builder.Add(spatialDialect.GetSpatialFilterString(alias, geometryColumn, keyColumn, tableName, p)); } return(builder.ToSqlString()); }
/// <summary> /// Get the column names for a given property as a comma-delimited string of unbracketed names. /// For a collection property, the column name is the inverse foreign key (i.e. the column on /// the other table that points back to the persister's table) /// </summary> /// <param name="persister"></param> /// <param name="propertyName"></param> /// <returns></returns> string GetPropertyColumnNames(AbstractEntityPersister persister, string propertyName, IType propType) { string[] propColumnNames = null; if (propType.IsCollectionType) { propColumnNames = ((CollectionType)propType).GetReferencedColumns((ISessionFactoryImplementor)this._sessionFactory); } else { propColumnNames = persister.GetPropertyColumnNames(propertyName); } if (propColumnNames == null || propColumnNames.Length == 0) { // this happens when the property is part of the key propColumnNames = persister.KeyColumnNames; } return(CatColumnNames(propColumnNames)); }
private static object CopyOnlyForeignKeyProperties(object entity, System.Type entityType, AbstractEntityPersister entityMetadata, DeepCloneOptions opts, DeepCloneParentEntity parentEntity) { var propertyInfos = entityType.GetProperties(); //Copy only Fks foreach (var propertyInfo in propertyInfos .Where(p => opts.CanCloneIdentifier(entityType) || entityMetadata.IdentifierPropertyName != p.Name) .Where(p => !opts.GetIgnoreMembers(entityType).Contains(p.Name)) .Where(p => p.GetSetMethod(true) != null)) { IType propertyType; try { propertyType = entityMetadata.GetPropertyType(propertyInfo.Name); } catch (Exception) { continue; } if (!NHibernateUtil.IsPropertyInitialized(entity, propertyInfo.Name)) { continue; } var propertyValue = propertyInfo.GetValue(entity, null); if (!NHibernateUtil.IsInitialized(propertyValue)) { continue; } var colNames = entityMetadata.GetPropertyColumnNames(propertyInfo.Name); if (!propertyType.IsEntityType) { continue; } //Check if we have a parent entity and that is bidirectional related to the current property (one-to-many) if (parentEntity.ReferencedColumns.SequenceEqual(colNames)) { propertyInfo.SetValue(entity, parentEntity.Entity, null); } } return(entity); }
/// <inheritdoc /> public IEntityBatchFetcher Create(AbstractEntityPersister persister) { ConstructorInfo constructor; if (persister.IdentifierPropertyName != null) { constructor = typeof(EntityBatchFetcher <,>) .MakeGenericType(persister.MappedClass, persister.IdentifierType.ReturnedClass) .GetConstructor(new[] { typeof(AbstractEntityPersister) }); } else { constructor = typeof(CompositeEntityBatchFetcher <>) .MakeGenericType(persister.MappedClass) .GetConstructor(new[] { typeof(AbstractEntityPersister) }); } return((IEntityBatchFetcher)constructor.Invoke(new object[] { persister })); }
/// <summary> /// Get the column names for a given property as a comma-delimited string of unbracketed names. /// </summary> /// <param name="persister"></param> /// <param name="propertyName"></param> /// <returns></returns> string GetPropertyColumnNames(AbstractEntityPersister persister, string propertyName) { var propColumnNames = persister.GetPropertyColumnNames(propertyName); if (propColumnNames.Length == 0) { // this happens when the property is part of the key propColumnNames = persister.KeyColumnNames; } var sb = new StringBuilder(); foreach (var s in propColumnNames) { if (sb.Length > 0) { sb.Append(','); } sb.Append(UnBracket(s)); } return(sb.ToString()); }
/// <summary> /// Gets the simple (non-Entity) property that has the given columns /// </summary> /// <param name="persister"></param> /// <param name="columnNames">Comma-delimited column name string</param> /// <returns></returns> string GetPropertyNameForColumn(AbstractEntityPersister persister, string columnNames) { var propNames = persister.PropertyNames; var propTypes = persister.PropertyTypes; for (int i = 0; i < propNames.Length; i++) { var propName = propNames[i]; var propType = propTypes[i]; if (propType.IsAssociationType) { continue; } var columnArray = persister.GetPropertyColumnNames(i); var columns = CatColumnNames(columnArray); if (columns == columnNames) { return(propName); } } return(persister.IdentifierPropertyName); }
/// <summary> /// Get the column names for a given property as a comma-delimited string of unbracketed names. /// For a collection property, the column name is the inverse foreign key (i.e. the column on /// the other table that points back to the persister's table) /// </summary> /// <param name="persister"></param> /// <param name="propertyName"></param> /// <param name="propType"></param> /// <returns></returns> string[] GetPropertyColumnNames(AbstractEntityPersister persister, string propertyName, IType propType) { string[] propColumnNames = null; if (propType.IsCollectionType) { propColumnNames = ((CollectionType)propType).GetReferencedColumns((ISessionFactoryImplementor)this._sessionFactory); } else { propColumnNames = persister.GetPropertyColumnNames(propertyName); } if (propColumnNames == null || propColumnNames.Length == 0) { // this happens when the property is part of the key propColumnNames = persister.KeyColumnNames; } // HACK for NHibernate formula: when using formula propColumnNames[0] equals null if (propColumnNames[0] == null) { propColumnNames = new string[] { propertyName }; } return(UnBracket(propColumnNames)); }
/// <summary> /// Make association property metadata for the entity. /// Also populates the ForeignKeyMap which is used for related-entity fixup in NHContext.FixupRelationships /// </summary> /// <param name="containingPersister">Entity Persister containing the property</param> /// <param name="propType">Association property</param> /// <param name="propName">Name of the property</param> /// <param name="dataProperties">Data properties already collected for the containingType. "isPartOfKey" may be added to a property.</param> /// <param name="isKey">Whether the property is part of the key</param> /// <returns></returns> private Dictionary <string, object> MakeAssociationProperty(AbstractEntityPersister containingPersister, IAssociationType propType, string propName, List <Dictionary <string, object> > dataProperties, bool isKey) { var nmap = new Dictionary <string, object>(); nmap.Add("nameOnServer", propName); var relatedEntityType = GetEntityType(propType.ReturnedClass, propType.IsCollectionType); nmap.Add("entityTypeName", relatedEntityType.Name + ":#" + relatedEntityType.Namespace); nmap.Add("isScalar", !propType.IsCollectionType); // the associationName must be the same at both ends of the association. Type containingType = containingPersister.EntityMetamodel.Type; string[] columnNames = GetPropertyColumnNames(containingPersister, propName, propType); nmap.Add("associationName", GetAssociationName(containingType.Name, relatedEntityType.Name, columnNames)); string[] fkNames = null; var joinable = propType.GetAssociatedJoinable((ISessionFactoryImplementor)this._sessionFactory); if (propType.IsCollectionType) { // inverse foreign key var collectionPersister = joinable as AbstractCollectionPersister; if (collectionPersister != null) { if (collectionPersister.IsManyToMany || collectionPersister.IsOneToMany) { // many-to-many relationships do not have a direct connection on the client or in metadata var elementPersister = collectionPersister.ElementPersister as AbstractEntityPersister; if (elementPersister != null) { fkNames = GetPropertyNamesForColumns(elementPersister, columnNames); if (fkNames != null) { nmap.Add("invForeignKeyNamesOnServer", fkNames); } } } } } else { // Not a collection type - a many-to-one or one-to-one association var entityRelationship = containingType.FullName + '.' + propName; // Look up the related foreign key name using the column name fkNames = GetPropertyNamesForColumns(containingPersister, columnNames); if (fkNames != null) { if (propType.ForeignKeyDirection == ForeignKeyDirection.ForeignKeyFromParent) { nmap.Add("foreignKeyNamesOnServer", fkNames); } else { nmap.Add("invForeignKeyNamesOnServer", fkNames); } // For many-to-one and one-to-one associations, save the relationship in ForeignKeyMap for re-establishing relationships during save _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", fkNames)); if (isKey) { foreach (var fkName in fkNames) { var relatedDataProperty = FindPropertyByName(dataProperties, fkName); if (!relatedDataProperty.ContainsKey("isPartOfKey")) { relatedDataProperty.Add("isPartOfKey", true); } } } } else if (fkNames == null) { nmap.Add("foreignKeyNamesOnServer", columnNames); nmap.Add("ERROR", "Could not find matching fk for property " + entityRelationship); _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", columnNames)); throw new ArgumentException("Could not find matching fk for property " + entityRelationship); } } return(nmap); }
public abstract string GetAuditNoteForComponentProperty(AbstractEntityPersister persister, ComponentType componentType, int propertyIndexToAudit);
public CompositeEntityBatchFetcher(AbstractEntityPersister persister) { // Embedded id _parameter = Expression.Parameter(typeof(TEntity)); }
/// <summary> /// Make association property metadata for the entity. /// Also populates the ForeignKeyMap which is used for related-entity fixup in NHContext.FixupRelationships /// </summary> /// <param name="containingPersister">Entity Persister containing the property</param> /// <param name="propType">Association property</param> /// <param name="propName">Name of the property</param> /// <param name="dataProperties">Data properties already collected for the containingType. "isPartOfKey" may be added to a property.</param> /// <param name="isKey">Whether the property is part of the key</param> /// <returns></returns> private Dictionary <string, object> MakeAssociationProperty(AbstractEntityPersister containingPersister, IAssociationType propType, string propName, List <Dictionary <string, object> > dataProperties, bool isKey) { var nmap = new Dictionary <string, object>(); nmap.Add("nameOnServer", propName); var relatedEntityType = GetEntityType(propType.ReturnedClass, propType.IsCollectionType); nmap.Add("entityTypeName", relatedEntityType.Name + ":#" + relatedEntityType.Namespace); nmap.Add("isScalar", !propType.IsCollectionType); // the associationName must be the same at both ends of the association. Type containingType = containingPersister.EntityMetamodel.Type; string[] columnNames = GetPropertyColumnNames(containingPersister, propName, propType); nmap.Add("associationName", GetAssociationName(containingType.Name, relatedEntityType.Name, columnNames)); var propertyIndex = containingPersister.PropertyNames.ToList().IndexOf(propName); var cascadeStyle = containingPersister.PropertyCascadeStyles[propertyIndex]; nmap.Add("hasOrphanDelete", cascadeStyle.HasOrphanDelete); string[] fkNames = null; var joinable = propType.GetAssociatedJoinable((ISessionFactoryImplementor)this._sessionFactory); var memberConfiguration = GetMemberConfiguration(containingType, propName); if (!string.IsNullOrEmpty(memberConfiguration.SerializedName)) { nmap.Add("name", memberConfiguration.SerializedName); } if (propType.IsCollectionType) { // inverse foreign key var collectionPersister = joinable as AbstractCollectionPersister; if (collectionPersister != null) { // many-to-many relationships do not have a direct connection on the client or in metadata var elementPersister = collectionPersister.ElementPersister as AbstractEntityPersister; if (elementPersister != null) { fkNames = GetPropertyNamesForColumns(elementPersister, columnNames); if (fkNames != null) { nmap.Add("invForeignKeyNamesOnServer", fkNames); } } } } else { // Not a collection type - a many-to-one or one-to-one association var entityRelationship = containingType.FullName + '.' + propName; // Look up the related foreign key name using the column name fkNames = GetPropertyNamesForColumns(containingPersister, columnNames); // TODO: support FK with multiple columns if (fkNames == null && columnNames.Length == 1) //try to find the column for the relation if is not specified in class { var pType = containingPersister.GetPropertyType(propName); var index = containingPersister.PropertyNames .Select((val, i) => new { Index = i, Value = val }) .Where(o => o.Value == propName) .Select(o => o.Index) .First(); var isNullable = containingPersister.PropertyNullability[index]; var convertedColumns = new List <string>(); foreach (var columnName in columnNames) { // TODO: convert columnName to c# name var synProp = new NHSyntheticProperty { Name = columnName, FkPropertyName = propName, FkType = pType, IsNullable = isNullable }; convertedColumns.Add(columnName); var relatedType = _sessionFactory.GetClassMetadata(synProp.FkType.Name); if (relatedType == null) { throw new ArgumentException("Could not find related entity of type " + synProp.FkType.Name); } synProp.PkType = relatedType.IdentifierType; synProp.PkPropertyName = relatedType.IdentifierPropertyName; if (!_syntheticProperties.ContainsKey(containingType)) { _syntheticProperties.Add(containingType, new List <NHSyntheticProperty>()); } _syntheticProperties[containingType].Add(synProp); //Create synthetic property as unmapped var dmap = MakeDataProperty(memberConfiguration, columnName, relatedType.IdentifierType, synProp.IsNullable, false, false); dmap["isUnmapped"] = true; dataProperties.Add(dmap); } fkNames = convertedColumns.ToArray(); } if (fkNames != null) { if (propType.ForeignKeyDirection == ForeignKeyDirection.ForeignKeyFromParent) { nmap.Add("foreignKeyNamesOnServer", fkNames); } else { nmap.Add("invForeignKeyNamesOnServer", fkNames); } // For many-to-one and one-to-one associations, save the relationship in ForeignKeyMap for re-establishing relationships during save _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", fkNames)); if (isKey) { foreach (var fkName in fkNames) { var relatedDataProperty = FindPropertyByName(dataProperties, fkName); if (!relatedDataProperty.ContainsKey("isPartOfKey")) { relatedDataProperty.Add("isPartOfKey", true); } } } } else if (fkNames == null) { nmap.Add("foreignKeyNamesOnServer", columnNames); nmap.Add("ERROR", "Could not find matching fk for property " + entityRelationship); _map.ForeignKeyMap.Add(entityRelationship, string.Join(",", columnNames)); throw new ArgumentException("Could not find matching fk for property " + entityRelationship); } } return(nmap); }
/// <summary> /// Gets the properties matching the given columns. May be a component, but will not be an association. /// </summary> /// <param name="persister"></param> /// <param name="columnNames">Array of column names</param> /// <returns></returns> static string[] GetPropertyNamesForColumns(AbstractEntityPersister persister, string[] columnNames) { var propNames = persister.PropertyNames; var propTypes = persister.PropertyTypes; for (int i = 0; i < propNames.Length; i++) { var propName = propNames[i]; var propType = propTypes[i]; if (propType.IsAssociationType) { continue; } var columnArray = persister.GetPropertyColumnNames(i); // HACK for NHibernate formula: when using formula GetPropertyColumnNames(i) returns an array with the first element null if (columnArray[0] == null) { continue; } if (NamesEqual(columnArray, columnNames)) { return new string[] { propName } } ; } // If we got here, maybe the property is the identifier var keyColumnArray = persister.KeyColumnNames; if (NamesEqual(keyColumnArray, columnNames)) { if (persister.IdentifierPropertyName != null) { return(new string[] { persister.IdentifierPropertyName }); } if (persister.IdentifierType.IsComponentType) { var compType = (ComponentType)persister.IdentifierType; return(compType.PropertyNames); } } if (columnNames.Length > 1) { // go one-by-one through columnNames, trying to find a matching property. // TODO: maybe this should split columnNames into all possible combinations of ordered subsets, and try those var propList = new List <string>(); var prop = new string[1]; for (int i = 0; i < columnNames.Length; i++) { prop[0] = columnNames[i]; var names = GetPropertyNamesForColumns(persister, prop); // recursive call if (names != null) { propList.AddRange(names); } } if (propList.Count > 0) { return(propList.ToArray()); } } return(null); }