【问题标题】:Parsing SQL Statement With Irony用 Irony 解析 SQL 语句
【发布时间】:2013-02-28 01:27:32
【问题描述】:

我正在尝试创建一个将常规 sql 语句转换为 c# 对象的方法,所以我决定使用 Irony 来解析 sql 语句,然后我将语句作为包含语句类型和值的操作返回它取决于类型

这是我未完成的代码 [因为我很沮丧,因为我不知道该怎么做]

private List<Action> ParseStatement(string statement)
{
    var parser = new Parser(new SqlGrammar());
    var parsed = parser.Parse(statement);
    var status = parsed.Status;

    while (parsed.Status == ParseTreeStatus.Parsing)
    {
        Task.Yield();
    }

    if (status == ParseTreeStatus.Error)
        throw new ArgumentException("The statement cannot be parsed.");

    ParseTreeNode parsedStmt = parsed.Root.ChildNodes[0];

    switch (parsedStmt.Term.Name)
    {
        case "insertStmt":
            var table = parsedStmt.ChildNodes.Find(x => x.Term.Name == "Id").ChildNodes[0].Token.ValueString;
            var valuesCount =
                parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
                    x => x.Term.Name == "exprList").ChildNodes.Count;
            var values = parsedStmt.ChildNodes.Find(x => x.Term.Name == "insertData").ChildNodes.Find(
                    x => x.Term.Name == "exprList").ChildNodes;
            foreach (var value in values)
            {
                string type = value.Token.Terminal.Name;
            }
            break;
    }

    return null;
}

private Type ParseType(string type)
{
    switch (type)
    {
        case "number":
            return typeof (int);
        case "string":
            return typeof (string);
    }

    return null;
}

所以这里的问题是:我如何利用 Irony 将字符串 SQL 语句转换为 c# 对象?

这是我想要实现的示例:

INSERT INTO Persons VALUES (4,'Nilsen', 'Johan', 'Bakken 2', '斯塔万格')

并将其转换为

return new Action<string type, string table, int val1, string val2, string val3, string val4, string val5>;

动态地取决于方法从语句中读取的内容。

我希望我已经很好地解释了我的想法,所以你们可以帮助我,如果有不清楚的地方请告诉我,我会尽力解释。

【问题讨论】:

  • 我猜你的出发点应该是获取合适的 SQL 语法并将其转换为 Irony 可以理解的语法格式。这不是一件容易的事。你愿意做很多不适合容易沮丧的人的工作。但它可以做到。
  • 我已经有了 SQLGrammar,但问题是解析每个语句、插入、更新、创建...然后返回其内容 [在 c# 中用于其他目的]
  • 您的问题是更多地与 Irony 解析您的 SQL 语句有关,还是更多地与基于解析结果执行转换有关?您对从 Irony 获得的 AST 满意吗?您能否展示一些您正在使用的相关 SQL 语法?
  • return the statement as an Action that contains the type of the statement and the values of it depending on the type 一个动作不包含任何值——它只是一个委托。你为什么要返回一个动作?
  • 这不就是 Linq 的用途吗?您可以只使用经过验证的 Linq-SQL 或实体框架,它们正是这样做的。重新发明轮子没有意义......

标签: c# sql irony


【解决方案1】:

我也尝试用 Irony 解析 SQL。我放弃了,因为 Irony 中的示例 SQL 解析器无法处理:CTE、按列号排序、一半的特殊语句,如

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

虽然我在学习 Irony 方面度过了愉快的时光,但我没有正确实现上述所有部分的编码能力。

我最终使用了 Microsoft 提供的 SQL 解析库。下面是 LINQPad 5 的示例代码:

// Add a reference to
// C:\Program Files (x86)\Microsoft SQL Server\130\SDK\Assemblies\
//   Microsoft.SqlServer.TransactSql.ScriptDom.dll
// 
// https://blogs.msdn.microsoft.com/gertd/2008/08/21/getting-to-the-crown-jewels/

public void Main()
{
    var sqlFilePath = @"C:\Users\Colin\Documents\Vonigo\database-scripts\Client\Estimate\spClient_EstimateAddNew.sql";
    bool fQuotedIdenfifiers = false;
    var parser = new TSql100Parser(fQuotedIdenfifiers);

    string inputScript = File.ReadAllText(sqlFilePath);
    IList<ParseError> errors;
    using (StringReader sr = new StringReader(inputScript))
    {
        var fragment = parser.Parse(sr, out errors);
        fragment.Dump();
    }
}

【讨论】:

    【解决方案2】:

    如果您不是将其作为一个有趣的练习,我建议您使用 Linq to SQL 来生成存根类或实体框架作为 cmets 中提到的 Drunken Code Monkey。

    这里有一篇很好的文章可以帮助您入门:Generating EF code from existing DB

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 2021-06-03
      • 1970-01-01
      相关资源
      最近更新 更多