0

假设我要解析sql语句

SELECT foo, bar, baz FROM myTable WHERE baz = 2 ORDER BY baz ASC, bar DESC

并以编程方式确定它排序的列和方向。经过一番谷歌搜索,这就是我想出的:

List<ParseError> Errors;
TSql100Parser parser = new TSql100Parser(true);
TSqlFragment result = parser.Parse(
    new StringReader("SELECT foo, bar, baz FROM myTable WHERE baz = 2 ORDER BY baz ASC, bar DESC"),
    out Errors);
foreach (var ts in (result as TSqlScript).Batches)
{
    foreach (var st in ts.Statements)
    {
        SelectStatement selectStatement = (SelectStatement) st;
        IList<ExpressionWithSortOrder> _list = selectStatement.QueryExpression.OrderByClause.OrderByElements;
        var c0 = _list[0].Expression as ColumnReferenceExpression;
        var c1 = _list[1].Expression as ColumnReferenceExpression;

        Assert.AreEqual("baz", c0.MultiPartIdentifier.Identifiers[0].Value);
        Assert.AreEqual("Ascending", _list[0].SortOrder.ToString());
        Assert.AreEqual("bar", c1.MultiPartIdentifier.Identifiers[0].Value);
        Assert.AreEqual("Descending", _list[1].SortOrder.ToString());
    }
}

这段代码工作正常,但我觉得它很混乱。在我看来,“as”关键字有两个地方很奇怪。

其中第一个在第 6 行。TsqlScript 是 TSqlFragment 的子类,所以我想我很幸运能够将它转换为子类。但是第 3 行 Parse 方法的返回类型 TSqlFragment 没有任何有用的属性,只有它的子类有有用的属性。那么,什么样的 API 会公开一个只有在您碰巧知道将其转换为其他东西时才有用的类?

“as”的第二个也是更容易混淆的用法,用在内部 foreach 中。我怎么可能将 ExpressionWithSortOrders 变成 ColumnReferenceExpressions?它们是类,而不是接口,并且它们不会相互继承。据我所知,它们之间既没有显式转换也没有隐式转换。

更一般地说,如何学习使用这样的 API?我在官方 scriptdom 文档中没有找到任何关于这个演员的信息。Visual Studio 没有告诉我可以将这些类相互转换。

4

1 回答 1

1

关于“第一种情况”:

MSDN 指出Parse您使用的方法的重载

使用提供的值返回脚本片段和错误列表。(继承自 TSqlParser。)

所以我想这应该足以知道它是一个TSqlScript类;-)

关于“第二种情况”:

    var c0 = _list[0].Expression as ColumnReferenceExpression;
    var c1 = _list[1].Expression as ColumnReferenceExpression;

我怎么可能将 ExpressionWithSortOrders 变成 ColumnReferenceExpressions?

但你没有。您将类的Expression属性ExpressionWithSortOrder转换为 a ColumnReferenceExpression,根据文档Expression,它与 type一样完全可以ScalarExpression,并ColumnReferenceExpression从中继承。

于 2015-12-09T15:30:41.970 回答