/// <summary>
        /// Constructs a grouper based on the contents of the given entity state manager.
        /// </summary>
        /// <param name="stateManager">Entity state manager containing changes to be processed.</param>
        /// <param name="metadataWorkspace">Metadata workspace.</param>
        /// <param name="connection">Map connection</param>
        /// <param name="commandTimeout">Timeout for update commands; null means 'use provider default'</param>
        private UpdateTranslator(IEntityStateManager stateManager, MetadataWorkspace metadataWorkspace, EntityConnection connection, int? commandTimeout)
        {
            EntityUtil.CheckArgumentNull(stateManager, "stateManager");
            EntityUtil.CheckArgumentNull(metadataWorkspace, "metadataWorkspace");
            EntityUtil.CheckArgumentNull(connection, "connection");

            // propagation state
            m_changes = new Dictionary<EntitySetBase, ChangeNode>();
            m_functionChanges = new Dictionary<EntitySetBase, List<ExtractedStateEntry>>();
            m_stateEntries = new List<IEntityStateEntry>();
            m_knownEntityKeys = new Set<EntityKey>();
            m_requiredEntities = new Dictionary<EntityKey, AssociationSet>();
            m_optionalEntities = new Set<EntityKey>();
            m_includedValueEntities = new Set<EntityKey>();

            // workspace state
            m_metadataWorkspace = metadataWorkspace;
            m_viewLoader = metadataWorkspace.GetUpdateViewLoader();
            m_stateManager = stateManager;

            // ancillary propagation services
            m_recordConverter = new RecordConverter(this);
            m_constraintValidator = new RelationshipConstraintValidator(this);

            m_providerServices = DbProviderServices.GetProviderServices(connection.StoreProviderFactory);
            m_connection = connection;
            m_commandTimeout = commandTimeout;

            // metadata cache
            m_extractorMetadata = new Dictionary<Tuple<EntitySetBase, StructuralType>, ExtractorMetadata>(); ;

            // key management
            KeyManager = new KeyManager(this);
            KeyComparer = CompositeKey.CreateComparer(KeyManager);
        }