2

パーミッション ツリーを構築するためのチェック ボックスを備えたコントロールがあります。ノードは、System.Windows.Forms.Treeviewコード ビハインドから追加されたカスタム ノードとともに、DB レコードから動的に構築されます。Allow AddAllow DeleteAllow Update

問題は、取得したツリーからチェック ノードを取得しようとするときですStackOverflowException

これが私のコードです:

List<tbl_JobPermission> SaveCheckedPermissions(int _JobID, System.Windows.Forms.TreeNodeCollection theNodes)
{
    using (WFMDBEntities _DBContext = new WFMDBEntities())
    {
        tbl_JobPermission _JopPermissionHelperVar;
        if (theNodes.Count > 0)
        {
            foreach (System.Windows.Forms.TreeNode aNode in theNodes.OfType<System.Windows.Forms.TreeNode>().Where(x => x.Checked == true))
            {
                int _tempJobPermID = int.Parse(aNode.Parent.Name);
                if (aNode.Name.Contains('_'))
                {
                    _JopPermissionHelperVar =
                            new tbl_JobPermission()
                            {
                                TblPremition = _tempJobPermID,
                                Tbljob = _JobID
                            };
                    if (aNode.Name.ToLower().Contains("add"))
                    {
                        _JopPermissionHelperVar.AllowNew = true;
                    }
                    else if (aNode.Name.ToLower().Contains("update"))
                    {
                        _JopPermissionHelperVar.AllowUpdate = true;
                    }
                    else if (aNode.Name.ToLower().Contains("delete"))
                    {
                        _JopPermissionHelperVar.AllowDelete = true;
                    }

                    if (!_JobPermissions.Contains(_JopPermissionHelperVar))
                    {
                        _JobPermissions.Add(_JopPermissionHelperVar);
                    }
                }
                else
                {
                    _JopPermissionHelperVar =
                            new tbl_JobPermission()
                            {
                                TblPremition = int.Parse(aNode.Name),
                                Tbljob = _JobID
                            };
                    if (!_JobPermissions.Contains(_JopPermissionHelperVar))
                    {
                        _JobPermissions.Add(_JopPermissionHelperVar);
                    }
                }
                if (aNode.Nodes.Count > 0)
                {
                    _JobPermissions.AddRange(SaveCheckedPermissions(_JobID, aNode.Nodes));
                }
            }
        }
    }
    return _JobPermissions;
}
4

2 に答える 2

1

StackOverFlow 例外が発生した理由がわかりました。問題はメソッドを再帰的に呼び出すことではなく、戻り値でした。メソッドを呼び出すたびに取得したデータのリストを返していたため、リスト項目が劇的に2倍になるので、私がしたことは単純でした==>メソッドの戻り値の型をリストではなくVoidにしました[そのList(クラススコープで宣言されている)を埋めるためです)

void SaveCheckedPermissions(int _JobID, System.Windows.Forms.TreeNode RootNode)
{
    using (WFMDBEntities _DBContext = new WFMDBEntities())
    {
        tbl_JobPermission _JopPermissionHelperVar;

        foreach (System.Windows.Forms.TreeNode aNode in RootNode.Nodes)
        {
            if (aNode.Checked == true)
            {
                int _tempJobPermID;
                int.TryParse(aNode.Name, out _tempJobPermID);
                _JopPermissionHelperVar = new tbl_JobPermission();
                _JopPermissionHelperVar.Tbljob = _JobID;
                if (aNode.Name.Contains('_'))
                {
                    int _tempSpecialJobPermID;
                    int.TryParse(aNode.Parent.Name, out _tempSpecialJobPermID);
                    if (_JobPermissions.Where(x => x.TblPremition == _tempSpecialJobPermID).FirstOrDefault() != null)
                    {
                        _JobPermissions.Where(x => x.TblPremition == _tempSpecialJobPermID).FirstOrDefault().TblPremition = _tempSpecialJobPermID;
                        if (aNode.Name.ToLower().Contains("add"))
                        {
                            _JobPermissions.Where(x => x.TblPremition == _tempSpecialJobPermID).FirstOrDefault().AllowNew = true;
                        }
                        else if (aNode.Name.ToLower().Contains("update"))
                        {
                            _JobPermissions.Where(x => x.TblPremition == _tempSpecialJobPermID).FirstOrDefault().AllowUpdate = true;
                        }
                        else if (aNode.Name.ToLower().Contains("delete"))
                        {
                            _JobPermissions.Where(x => x.TblPremition == _tempSpecialJobPermID).FirstOrDefault().AllowDelete = true;
                        }
                    }
                }
                else
                {
                    if (_JobPermissions.Where(x => x.TblPremition == _tempJobPermID).FirstOrDefault() == null)
                    {
                        _JopPermissionHelperVar.TblPremition = _tempJobPermID;
                    }

                }

                if (_JobPermissions.Where(x => x.TblPremition == _JopPermissionHelperVar.TblPremition && x.Tbljob == _JopPermissionHelperVar.Tbljob).ToList().Count < 1)
                {
                    _JobPermissions.Add(_JopPermissionHelperVar);
                }
            }
            SaveCheckedPermissions(_JobID, aNode);
        }
    }
}
于 2013-03-20T09:49:37.610 に答える
1

ここに再帰呼び出しがあります:

if (aNode.Nodes.Count > 0)
{
    _JobPermissions.AddRange(SaveCheckedPermissions(_JobID, aNode.Nodes));
}

デバッガーで実行して、再帰する前にノードの数を減らしたことを確認してください。

すべてのノードを特定のレベルでチェックすると、無限に再帰すると思います。

[編集]

ノード レベルが多すぎる可能性があります。クラッシュする前に何レベルの再帰に到達しますか? Debug.WriteLines で計測できますか?

于 2013-03-19T15:29:18.127 に答える