// <summary>
        //
        // </summary>
        /// <summary>
        /// Create a new, fresh, empty Node from a node type.  Properties are filled in, but Property Values are not. !!POSTS CHANGES!!
        /// </summary>
        /// <param name="NodeTypeId">Primary Key of Nodetype</param>
        /// <param name="IsTemp">If true, the node is a temp node, though still saved to the database</param>
        /// <param name="OnAfterMakeNode">Event that occurs after creating the node but before saving it for the first time</param>
        /// <param name="OverrideUniqueValidation">If true, allow this node to be created even if it violates uniqueness rules</param>
        /// <returns>The new node. !!POSTS CHANGES!!</returns>
        public CswNbtNode makeNodeFromNodeTypeId(Int32 NodeTypeId, Action <CswNbtNode> OnAfterMakeNode = null, bool IsTemp = false, bool OverrideUniqueValidation = false, bool IsCopy = false, bool OverrideMailReportEvents = false)
        {
            CswNbtNode Node = new CswNbtNode(_CswNbtResources, _CswNbtNodeWriter, NodeTypeId, CswEnumNbtNodeSpecies.Plain, null, _NodeHash.Count, null, IsTemp: true);   // temp here for auditing, but see below

            //Node.OnAfterSetNodeId += new CswNbtNode.OnSetNodeIdHandler( OnAfterSetNodeIdHandler );
            Node.fillFromNodeTypeId();

            _CswNbtNodeWriter.makeNewNodeEntry(Node);
            _CswNbtNodeWriter.setDefaultPropertyValues(Node);

            if (null != OnAfterMakeNode)
            {
                OnAfterMakeNode(Node);
            }

            // We need to hash the Int32.MinValue keys for the Add form to work
            // But we can simply override what's in the hash if we make another new node
            NodeHashKey Hashkey = new NodeHashKey(Node.NodeId, Node.NodeSpecies);

            _NodeHash[Hashkey] = Node;

            ICswNbtNodePersistStrategy NodePersistStrategy;

            if (false == IsTemp)
            {
                NodePersistStrategy          = new CswNbtNodePersistStrategyPromoteReal(_CswNbtResources);
                NodePersistStrategy.Creating = true;
            }
            else
            {
                NodePersistStrategy = new CswNbtNodePersistStrategyCreateTemp(_CswNbtResources);
            }

            // only override the defaults on these if they are true
            if (OverrideUniqueValidation)
            {
                NodePersistStrategy.OverrideUniqueValidation = true;
            }
            if (IsCopy)
            {
                NodePersistStrategy.IsCopy = true;
            }
            if (OverrideMailReportEvents)
            {
                NodePersistStrategy.OverrideMailReportEvents = true;
            }

            NodePersistStrategy.postChanges(Node);

            return(Node);
        }//makeNodeFromNodeTypeId()
        /// <remark>
        /// We need a NodeTypeId because the NodeId is missing from the HashKey if this is a new node we're about to add
        /// </remark>
        private CswNbtNode _getExistingNode(NodeHashKey HashKey, Int32 NodeTypeId, CswDateTime Date)
        {
            CswTimer   Timer = new CswTimer();
            CswNbtNode Node  = new CswNbtNode(_CswNbtResources, _CswNbtNodeWriter, NodeTypeId, CswEnumNbtNodeSpecies.Plain, HashKey.NodeId, _NodeHash.Count, Date);

            //bz # 7816 -- only add to the collection if the node got filled
            Node.fill();
            if (Node.Filled)
            {
                if (!_NodeHash.ContainsKey(HashKey))
                {
                    _NodeHash.Add(HashKey, Node);
                }
                _CswNbtResources.logTimerResult("CswNbtNodeCollection.makeNode on NodeId (" + HashKey.NodeId.ToString() + ")", Timer.ElapsedDurationInSecondsAsString);
            }
            else
            {
                Node = null;
            }
            return(Node);
        }
        /// <summary>
        /// Fetches just the nodename of a node, by primary key
        /// </summary>
        public string getNodeName(CswPrimaryKey NodeId)
        {
            string      ret     = string.Empty;
            NodeHashKey hashKey = new NodeHashKey(NodeId, CswEnumNbtNodeSpecies.Plain);

            if (_NodeHash.ContainsKey(hashKey))
            {
                ret = _NodeHash[hashKey].NodeName;
            }
            else
            {
                CswTableSelect NodeSelect = _CswNbtResources.makeCswTableSelect("getNodeName_select", "nodes");
                DataTable      NodeTable  = NodeSelect.getTable(new CswCommaDelimitedString()
                {
                    "nodename"
                }, "nodeid", NodeId.PrimaryKey, string.Empty, false);
                if (NodeTable.Rows.Count > 0)
                {
                    ret = CswConvert.ToString(NodeTable.Rows[0]["nodename"]);
                }
            }
            return(ret);
        } // getNodeName()
        /// <summary>
        /// Fetch a node from the collection.  If the node isn't loaded from the database already, it will be.
        /// NodeTypeId is only required if you don't provide a good NodeId (so that we can still fetch Property info).
        /// </summary>
        /// <param name="NodeId">Primary Key of Node (if not provided, make sure NodeTypeId is)</param>
        /// <param name="NodeTypeId">Primary Key of NodeTypeId (only required if NodeId is invalid)</param>
        /// <param name="Species"><see cref="CswEnumNbtNodeSpecies" /></param>
        /// <param name="Date"></param>
        public CswNbtNode GetNode(CswPrimaryKey NodeId, Int32 NodeTypeId, CswEnumNbtNodeSpecies Species, CswDateTime Date)
        {
            //bz # 7816: Return NULL rather than throwing
            CswNbtNode Node = null;

            if (NodeId != null && NodeId.PrimaryKey != Int32.MinValue)   // BZ 8753
            {
                NodeHashKey HashKey = new NodeHashKey(NodeId, Species);
                if (false == CswTools.IsDate(Date) && _NodeHash.ContainsKey(HashKey))
                {
                    Node = (CswNbtNode)_NodeHash[HashKey];
                }
                else
                {
                    Node = _getExistingNode(HashKey, NodeTypeId, Date);
                    //if( false == CswTools.IsDate( Date ) && null != Node )
                    //{
                    //    Node = (CswNbtNode) _NodeHash[HashKey];
                    //}
                }
            }
            return(Node);
        }//GetNode()