Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从树视图节点生成SQL查询_C#_.net - Fatal编程技术网

C# 从树视图节点生成SQL查询

C# 从树视图节点生成SQL查询,c#,.net,C#,.net,我正在尝试构建简单的sql查询编辑器,我需要能够编辑查询条件(位于WHERE关键字之后)。 我有一个树,显示如下所示的条件: 我无法将节点转换为正确的SQL代码 我可以在节点上迭代,但这给了我以下结果: AND Name = John OR Surname = Smith Lastname = Smith 但是我需要这个(有效的SQL): 我该怎么做 下面是我用来扩展TreeNode和从截图创建示例的代码: public partial class Form1 : Form { pu

我正在尝试构建简单的sql查询编辑器,我需要能够编辑查询条件(位于
WHERE
关键字之后)。
我有一个树,显示如下所示的条件:

我无法将节点转换为正确的SQL代码

我可以在节点上迭代,但这给了我以下结果:

AND
Name = John
OR
Surname = Smith
Lastname = Smith
但是我需要这个(有效的SQL):

我该怎么做

下面是我用来扩展TreeNode和从截图创建示例的代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        var root = new OperatorNode(OperatorType.AND);
        var treeNode = new SqlTextNode("Name", ContitionType.EQUAL, "John");
        root.Nodes.Add(treeNode);
        var orNode = new OperatorNode(OperatorType.OR);
        var node2 = new SqlTextNode("Surname",ContitionType.EQUAL, "Smith");
        var node3 = new SqlTextNode("Lastname",ContitionType.EQUAL, "Smith");
        orNode.Nodes.Add(node2);
        orNode.Nodes.Add(node3);
        root.Nodes.Add(orNode);
        treeView1.Nodes.Add(root);
        treeView1.ExpandAll();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        CallRecursive(treeView1);
    }

    private void PrintRecursive(TreeNode treeNode)
    {
        Debug.WriteLine(treeNode.Text);
        foreach (TreeNode tn in treeNode.Nodes)
        {
            PrintRecursive(tn);
        }
    }

    private void CallRecursive(TreeView treeView)
    {
        TreeNodeCollection nodes = treeView.Nodes;
        foreach (TreeNode n in nodes)
        {
            PrintRecursive(n);
        }
    }
}

public class OperatorNode : TreeNode
{
    private OperatorType _operator;

    public OperatorType Operator
    {
        get { return _operator; }
        set
        {
            if(value==_operator) return;
            _operator = value;
            Text = _operator.ToString();
        }
    }

    public OperatorNode(OperatorType @operator) : base(@operator.ToString())
    {
        _operator = @operator;
    }
}

public class SqlTextNode : TreeNode
{
    private string _fieldName;
    private ContitionType _condition;
    private string _value;


    public SqlTextNode(string fieldName, ContitionType condition, string value)
    {
        _fieldName = fieldName;
        _condition = condition;
        _value = value;
        UpdateText();
    }

    public string FieldName
    {
        get { return _fieldName; }
        set
        {
            if (value == _fieldName) return;
            _fieldName = value;
            UpdateText();
        }
    }

    public ContitionType Condition
    {
        get { return _condition; }
        set
        {
            if (value == _condition) return;
            _condition = value;
            UpdateText();
        }
    }

    public string Value
    {
        get { return _value; }
        set
        {
            if (value == _value) return;
            _value = value;
            UpdateText();
        }
    }

    private void UpdateText()
    {
        Text = string.Format("{0} {1} {2}", _fieldName, Enums.GetEnumDescription(_condition), _value);
    }
}

public enum OperatorType
{
    AND,
    OR
}

public enum ContitionType
{
    EQUAL,
    NOT_EQUAL
}

public static class Enums
{
    public static string GetEnumDescription(Enum value)
    {
        FieldInfo fi = value.GetType().GetField(value.ToString());

        DescriptionAttribute[] attributes =
            (DescriptionAttribute[])fi.GetCustomAttributes(
            typeof(DescriptionAttribute),
            false);

        return attributes.Length > 0 ? attributes[0].Description : value.ToString();
    }
}

有两种不同类型的节点:
OperatorNode
SqlTextNode
。您可以轻松检查节点的类型并执行相应的操作:

  • 如果节点是
    SqlTextNode
    ,只需像以前那样打印即可

  • 如果节点是
    OperatorNode
    ,则需要使用
    ()
    覆盖所有子节点,并在它们之间插入运算符

该算法可以通过多种不同的方式实现,但我将添加一个简单的示例:

private void PrintRecursive(TreeNode treeNode, int indentation)
{
    var indent = new string(' ', indentation * IndentSize);
    // SqlTextNode doesn't have children
    if (treeNode is SqlTextNode)
        Debug.WriteLine(indent + treeNode.Text);
    else
    {
        Debug.WriteLine(indent + "(");
        for (int i=0; i<treeNode.Nodes.Count; i++ )
        { 
            PrintRecursive(treeNode.Nodes[i], indentation+1);
            if (i!=treeNode.Nodes.Count-1)
            {
                // print the operator
                indent = new string(' ', (indentation+1) * IndentSize);                
                Debug.WriteLine(indent + treeNode.Text);
            }
        }
        Debug.WriteLine(indent + ")");
    }
}
private void PrintRecursive(TreeNode TreeNode,int缩进)
{
var indent=新字符串(“”,缩进*缩进大小);
//SqlTextNode没有子节点
if(treeNode是SqlTextNode)
Debug.WriteLine(缩进+树节点.Text);
其他的
{
Debug.WriteLine(缩进+“(”);

对于(inti=0;i这是我的答案:
我已在自定义节点类型中重写了
ToString

public class OperatorNode : TreeNode
{
    private OperatorType _operator;

    public OperatorType Operator
    {
        get { return _operator; }
        set
        {
            if(value==_operator) return;
            _operator = value;
            Text = _operator.ToString();
        }
    }

    public OperatorNode(OperatorType @operator) : base(@operator.ToString())
    {
        _operator = @operator;
    }

    public override string ToString()
    {
        List<string> n = (from TreeNode node in Nodes select node.ToString()).ToList();

        return " ( " + string.Join(Environment.NewLine + _operator + " ", n) + " ) ";
    }
}

public class SqlTextNode : TreeNode
{
    private string _fieldName;
    private ContitionType _condition;
    private string _value;


    public SqlTextNode(string fieldName, ContitionType condition, string value)
    {
        _fieldName = fieldName;
        _condition = condition;
        _value = value;

        UpdateText();
    }

    public override string ToString()
    {
        return string.Format("{0} {1} {2}", _fieldName, _condition.GetDescription(), _value);
    }

    public string FieldName
    {
        get { return _fieldName; }
        set
        {
            if (value == _fieldName) return;
            _fieldName = value;
            UpdateText();
        }
    }

    public ContitionType Condition
    {
        get { return _condition; }
        set
        {
            if (value == _condition) return;
            _condition = value;
            UpdateText();
        }
    }

    public string Value
    {
        get { return _value; }
        set
        {
            if (value == _value) return;
            _value = value;
            UpdateText();
        }
    }

    private void UpdateText()
    {
        Text = string.Format("{0} {1} {2}", _fieldName, _condition.GetDescription(), _value);
    }
}
公共类运算符节点:TreeNode
{
私人运营商类型_运营商;
公共运算符类型运算符
{
获取{return\u操作符;}
设置
{
if(value==_运算符)返回;
_运算符=值;
Text=_运算符.ToString();
}
}
公共运算符节点(运算符类型@operator):基(@operator.ToString())
{
_运算符=@运算符;
}
公共重写字符串ToString()
{
列表n=(从节点中的TreeNode节点选择node.ToString()).ToList();
返回“(“+string.Join(Environment.NewLine++\u operator+”,n)+”);
}
}
公共类SqlTextNode:TreeNode
{
私有字符串_fieldName;
私有ConditionType_条件;
私有字符串_值;
公共SqlTextNode(字符串字段名、ConditionType条件、字符串值)
{
_fieldName=fieldName;
_条件=条件;
_价值=价值;
UpdateText();
}
公共重写字符串ToString()
{
返回string.Format(“{0}{1}{2}”,_fieldName,_condition.GetDescription(),_value);
}
公共字符串字段名
{
获取{return\u fieldName;}
设置
{
if(value==\u fieldName)返回;
_字段名=值;
UpdateText();
}
}
公共连续型条件
{
获取{返回_条件;}
设置
{
如果(值==_条件)返回;
_条件=值;
UpdateText();
}
}
公共字符串值
{
获取{返回_值;}
设置
{
如果(值==_值)返回;
_价值=价值;
UpdateText();
}
}
私有void UpdateText()
{
Text=string.Format(“{0}{1}{2}”,_字段名,_条件.GetDescription(),_值);
}
}
这样,每个节点都有负责创建查询部分的逻辑。
因此,我可以使用以下函数生成完整查询:

private void PrintQuery(TreeView treeView)
{
    string s = string.Empty;
    TreeNodeCollection nodes = treeView.Nodes;
    s = nodes.Cast<TreeNode>().Aggregate(s, (current, n) => current + (n.ToString() + Environment.NewLine)).Trim();

    //remove unwanted brackets
    s = s.Remove(s.Length - 1).Substring(1).Trim();
    textBox1.Text = s;
}
private void打印查询(TreeView TreeView)
{
string s=string.Empty;
TreeNodeCollection节点=treeView.nodes;
s=nodes.Cast().Aggregate(s,(current,n)=>current+(n.ToString()+Environment.NewLine)).Trim();
//移除不需要的支架
s=s.Remove(s.Length-1).Substring(1).Trim();
textBox1.Text=s;
}
输出没有缩进,但我不必显示最终查询,这只是调试的临时结果


我知道我必须用单引号转义条件值,但这是最简单的部分:)

将节点限制为二进制将使事情变得更容易。然后,您可以使用simple@Domysee感谢链接,但我不能将节点限制为两个子节点。我希望在
组中有多个条件
private void PrintQuery(TreeView treeView)
{
    string s = string.Empty;
    TreeNodeCollection nodes = treeView.Nodes;
    s = nodes.Cast<TreeNode>().Aggregate(s, (current, n) => current + (n.ToString() + Environment.NewLine)).Trim();

    //remove unwanted brackets
    s = s.Remove(s.Length - 1).Substring(1).Trim();
    textBox1.Text = s;
}