Exemplo n.º 1
0
            private bool IsProcessedAfterAllAssociatedEntities(EntityInsertAction action, int latestBatchNumberForType)
            {
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.ClassMetadata.PropertyTypes;

                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(false);
                        }
                    }
                }

                return(true);
            }
Exemplo n.º 2
0
            private int GetBatchNumber(EntityInsertAction 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 (IsProcessedAfterAllAssociatedEntities(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);
            }
Exemplo n.º 3
0
            private void UpdateChildrenDependencies(int batchNumber, EntityInsertAction action)
            {
                var propertyValues = action.State;
                var propertyTypes  = action.Persister.EntityMetamodel?.PropertyTypes;

                if (propertyTypes == null)
                {
                    log.WarnFormat(
                        "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;
                    }
                }
            }
Exemplo n.º 4
0
            private void AddToBatch(int batchNumber, EntityInsertAction action)
            {
                List <EntityInsertAction> actions;

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

                actions.Add(action);
            }
Exemplo n.º 5
0
            private bool RequireNewBatch(EntityInsertAction 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.InfoFormat(
                        "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);
            }
Exemplo n.º 6
0
 public void AddAction(EntityInsertAction action)
 {
     insertions.Add(action);
 }
Exemplo n.º 7
0
        //Order the {@link #insertions} queue such that we group inserts
        //against the same entity together (without violating constraints).  The
        //original order is generated by cascade order, which in turn is based on
        //the directionality of foreign-keys. So even though we will be changing
        //the ordering here, we need to make absolutely certain that we do not
        //circumvent this FK ordering to the extent of causing constraint
        //violations
        private void SortInsertActions()
        {
            // IMPLEMENTATION NOTES:
            //
            // The main data structure in this ordering algorithm is the 'positionToAction'
            // map. Essentially this can be thought of as an put-ordered map (the problem with
            // actually implementing it that way and doing away with the 'nameList' is that
            // we'd end up having potential duplicate key values).  'positionToAction' maintains
            // a mapping from a position within the 'nameList' structure to a "partial queue"
            // of actions.

            Dictionary <int, List <EntityInsertAction> > positionToAction =
                new Dictionary <int, List <EntityInsertAction> >();
            List <string> nameList = new List <string>();

            while (!(insertions.Count == 0))
            {
                // todo-events : test behaviour
                // in Java they use an implicit cast to EntityInsertAction
                // but it may be not work because the insertions list may contain EntityIdentityInsertAction
                // (I don't like that "goto"too)
                object tempObject = insertions[0];
                insertions.RemoveAt(0);
                EntityInsertAction action         = (EntityInsertAction)tempObject;
                string             thisEntityName = action.EntityName;

                // see if we have already encountered this entity-name...
                if (!nameList.Contains(thisEntityName))
                {
                    // we have not, so create the proper entries in nameList and positionToAction
                    List <EntityInsertAction> segmentedActionQueue = new List <EntityInsertAction>();
                    segmentedActionQueue.Add(action);
                    nameList.Add(thisEntityName);
                    positionToAction[nameList.IndexOf(thisEntityName)] = segmentedActionQueue;
                }
                else
                {
                    // we have seen it before, so we need to determine if this insert action is
                    // is dependent upon a previously processed action in terms of FK
                    // relationships (this FK checking is done against the entity's property-state
                    // associated with the action...)
                    int      lastPos = nameList.LastIndexOf(thisEntityName);
                    object[] states  = action.State;
                    for (int i = 0; i < states.Length; i++)
                    {
                        for (int j = 0; j < nameList.Count; j++)
                        {
                            List <EntityInsertAction> tmpList = positionToAction[j];
                            for (int k = 0; k < tmpList.Count; k++)
                            {
                                EntityInsertAction checkAction = tmpList[k];
                                if (checkAction.Instance == states[i] && j > lastPos)
                                {
                                    // 'checkAction' is inserting an entity upon which 'action' depends...
                                    // note: this is an assumption and may not be correct in the case of one-to-one
                                    List <EntityInsertAction> segmentedActionQueue = new List <EntityInsertAction>();
                                    segmentedActionQueue.Add(action);
                                    nameList.Add(thisEntityName);
                                    positionToAction[nameList.LastIndexOf(thisEntityName)] = segmentedActionQueue;
                                    goto loopInsertion;
                                }
                            }
                        }
                    }

                    List <EntityInsertAction> actionQueue = positionToAction[lastPos];
                    actionQueue.Add(action);
                }
                loopInsertion :;
            }

            // now iterate back through positionToAction map and move entityInsertAction back to insertion list
            for (int p = 0; p < nameList.Count; p++)
            {
                List <EntityInsertAction> actionQueue = positionToAction[p];
                foreach (EntityInsertAction action in actionQueue)
                {
                    insertions.Add(action);
                }
            }
        }