Я знаю, что вопрос был о .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-запрос не является нулевым или пустым, потому что синтаксический анализатор считает, что пустая строка совершенно допустима (и я не осуждаю ее).
Как проверить?
Существует три теста 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);
}
}