C# 从树视图节点生成SQL查询
我正在尝试构建简单的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
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;
}