예제 #1
0
            private void UpdateChildrenDependencies(int batchNumber, AbstractEntityInsertAction action)
            {
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.EntityMetamodel?.PropertyTypes;

                if (propertyTypes == null)
                {
                    log.Warn(
                        "Entity {0} persister does not provide meta-data: if there is dependent entities providing " +
                        "meta-data, they may get batched before this one and cause a failure.",
                        action.EntityName);
                    return;
                }

                var sessionFactory = action.Session.Factory;

                for (var i = 0; i < propertyValues.Length; i++)
                {
                    var type = propertyTypes[i];

                    if (!type.IsCollectionType)
                    {
                        continue;
                    }

                    var collectionType      = (CollectionType)type;
                    var collectionPersister = sessionFactory.GetCollectionPersister(collectionType.Role);
                    if (collectionPersister.IsManyToMany || !collectionPersister.ElementType.IsEntityType)
                    {
                        continue;
                    }

                    var children = propertyValues[i] as IEnumerable;
                    if (children == null)
                    {
                        continue;
                    }

                    foreach (var child in children)
                    {
                        if (child == null)
                        {
                            continue;
                        }

                        int latestDependency;
                        if (_entityBatchDependency.TryGetValue(child, out latestDependency) && latestDependency > batchNumber)
                        {
                            continue;
                        }

                        _entityBatchDependency[child] = batchNumber;
                    }
                }
            }
예제 #2
0
            private void AddToBatch(int batchNumber, AbstractEntityInsertAction action)
            {
                List <AbstractEntityInsertAction> actions;

                if (!_actionBatches.TryGetValue(batchNumber, out actions))
                {
                    actions = new List <AbstractEntityInsertAction>();
                    _actionBatches[batchNumber] = actions;
                }

                actions.Add(action);
            }
예제 #3
0
            private bool RequireNewBatch(AbstractEntityInsertAction action, int latestBatchNumberForType)
            {
                // This method assumes the original action list is already sorted in order to respect dependencies.
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.EntityMetamodel?.PropertyTypes;

                if (propertyTypes == null)
                {
                    log.Info(
                        "Entity {0} persister does not provide meta-data, giving up batching grouping optimization for this entity.",
                        action.EntityName);
                    // Cancel grouping optimization for this entity.
                    return(true);
                }

                int latestDependency;

                if (_entityBatchDependency.TryGetValue(action.Instance, out latestDependency) && latestDependency > latestBatchNumberForType)
                {
                    return(true);
                }

                for (var i = 0; i < propertyValues.Length; i++)
                {
                    var value = propertyValues[i];
                    var type  = propertyTypes[i];

                    if (type.IsEntityType && value != null &&
                        // If the value is not initialized, it is a proxy with pending load from database,
                        // so it can only be an already persisted entity. It can not have its own pending
                        // insertion batch. So there is no need to seek for it, and it avoids initializing
                        // it by searching it in a dictionary. Fixes #1338.
                        NHibernateUtil.IsInitialized(value))
                    {
                        // find the batch number associated with the current association, if any.
                        int associationBatchNumber;
                        if (_entityBatchNumber.TryGetValue(value, out associationBatchNumber) &&
                            associationBatchNumber > latestBatchNumberForType)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
예제 #4
0
            private bool RequireNewBatch(AbstractEntityInsertAction action, int latestBatchNumberForType)
            {
                // This method assumes the original action list is already sorted in order to respect dependencies.
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.EntityMetamodel?.PropertyTypes;

                if (propertyTypes == null)
                {
                    log.Info(
                        "Entity {0} persister does not provide meta-data, giving up batching grouping optimization for this entity.",
                        action.EntityName);
                    // Cancel grouping optimization for this entity.
                    return(true);
                }

                int latestDependency;

                if (_entityBatchDependency.TryGetValue(action.Instance, out latestDependency) && latestDependency > latestBatchNumberForType)
                {
                    return(true);
                }

                for (var i = 0; i < propertyValues.Length; i++)
                {
                    var value = propertyValues[i];
                    var type  = propertyTypes[i];

                    if (type.IsEntityType && value != null)
                    {
                        // find the batch number associated with the current association, if any.
                        int associationBatchNumber;
                        if (_entityBatchNumber.TryGetValue(value, out associationBatchNumber) &&
                            associationBatchNumber > latestBatchNumberForType)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
예제 #5
0
            private int GetBatchNumber(AbstractEntityInsertAction action, string entityName)
            {
                int batchNumber;

                if (_latestBatches.TryGetValue(entityName, out batchNumber))
                {
                    // There is already an existing batch for this type of entity.
                    // Check to see if the latest batch is acceptable.
                    if (!RequireNewBatch(action, batchNumber))
                    {
                        return(batchNumber);
                    }
                }

                // add an entry for this type of entity.
                // we can be assured that all referenced entities have already
                // been processed,
                // so specify that this entity is with the latest batch.
                // doing the batch number before adding the name to the list is
                // a faster way to get an accurate number.
                batchNumber = _actionBatches.Count;
                _latestBatches[entityName] = batchNumber;
                return(batchNumber);
            }
예제 #6
0
            private void UpdateChildrenDependencies(int batchNumber, AbstractEntityInsertAction action)
            {
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.EntityMetamodel?.PropertyTypes;

                if (propertyTypes == null)
                {
                    log.Warn(
                        "Entity {0} persister does not provide meta-data: if there is dependent entities providing " +
                        "meta-data, they may get batched before this one and cause a failure.",
                        action.EntityName);
                    return;
                }

                var sessionFactory = action.Session.Factory;

                for (var i = 0; i < propertyValues.Length; i++)
                {
                    var type = propertyTypes[i];

                    if (!type.IsCollectionType)
                    {
                        continue;
                    }

                    var collectionType      = (CollectionType)type;
                    var collectionPersister = sessionFactory.GetCollectionPersister(collectionType.Role);
                    if (collectionPersister.IsManyToMany || !collectionPersister.ElementType.IsEntityType)
                    {
                        continue;
                    }

                    var children = propertyValues[i] as IEnumerable;
                    if (children == null)
                    {
                        continue;
                    }

                    foreach (var child in children)
                    {
                        if (child == null ||
                            // If the child is not initialized, it is a proxy with pending load from database,
                            // so it can only be an already persisted entity. It can not have its own pending
                            // insertion batch. So we do not need to keep track of the highest other batch on
                            // which it depends. And this avoids initializing the proxy by searching it into
                            // a dictionary.
                            !NHibernateUtil.IsInitialized(child))
                        {
                            continue;
                        }

                        int latestDependency;
                        if (_entityBatchDependency.TryGetValue(child, out latestDependency) && latestDependency > batchNumber)
                        {
                            continue;
                        }

                        _entityBatchDependency[child] = batchNumber;
                    }
                }
            }