我知道这个问题是关于 .NET 2.0 的,但对某些人来说可能很有趣。在最新版本的 Microsoft SQL Server 中,查询的验证略有变化。
命名空间是 Microsoft.SqlServer.TransactSql.ScriptDom 而不是 Microsoft.Data.Schema.ScriptDom。
在哪里可以找到这个库?
库的路径是%programfiles(x86)%\Microsoft SQL Server\120\SDK\Assemblies
如果找不到该库且安装了 Microsoft SQL Server,请尝试将120 更改为110 或100 并使用相应的解析器(分别为TSql110Parser 或TSql100Parser)。
如何使用?
我有两个扩展:第一个扩展检查输入字符串是否是有效的 SQL 查询,第二个可用于从解析中获取错误。
using Microsoft.SqlServer.TransactSql.ScriptDom;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public static class SqlStringExtensions
{
public static bool IsValidSql(this string str)
{
return !str.ValidateSql().Any();
}
public static IEnumerable<string> ValidateSql(this string str)
{
if (string.IsNullOrWhiteSpace(str))
{
return new[] { "SQL query should be non empty." };
}
var parser = new TSql120Parser(false);
IList<ParseError> errors;
using (var reader = new StringReader(str))
{
parser.Parse(reader, out errors);
}
return errors.Select(err => err.Message);
}
}
另外,我检查输入 SQL 查询不为 null 或空,因为解析器认为空字符串是完全有效的(我不判断它)。
如何测试?
有三个 NUnit 测试展示了如何使用这个扩展。
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
[TestFixture]
public class SqlStringExtensionsTests
{
[Test]
public void ValidateSql_InvalidSql_ReturnsErrorMessages()
{
// this example doesn't contain "," between the field names
string invalidSql = "SELECT /*comment*/ " +
"CustomerID AS ID CustomerNumber FROM Customers";
IEnumerable<string> results = invalidSql.ValidateSql();
Assert.AreNotEqual(0, results.Count());
}
[Test]
public void IsValidSql_ValidSql_ReturnsTrue()
{
string validSql = "SELECT /*comment*/ " +
"CustomerID AS ID, CustomerNumber FROM Customers";
bool result = validSql.IsValidSql();
Assert.AreEqual(true, result);
}
[Test]
public void IsValidSql_InvalidSql_ReturnsFalse()
{
// this example doesn't contain "," between the field names
string invalidSql = "SELECT /*comment*/ "+
" CustomerID AS ID CustomerNumber FROM Customers";
bool result = invalidSql.IsValidSql();
Assert.AreEqual(false, result);
}
}