SqlDataAdapter.FillSchema не получает DataTable на SQL 2017 - PullRequest
0 голосов
/ 20 ноября 2018

Я не знаю почему, но когда я выполняю этот код на MSSQL 2012 и 2015, все работает нормально (я получаю схему DataTable в объявленный DataSet), тогда как когда я делаю это на MSSQL 2017- FillSchema НИЧЕГО не помещает в DataSet.

DataSet.Tables.Count равно 0.

Ниже приведен пример кода:

var da = new SqlDataAdapter();
var cn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Test"].ConnectionString);
try
{
    cn.Open();
    var sql = "SELECT * FROM MyTable T" +
        "WHERE T.MyTableId=123 AND " +
        "EXISTS" +
        "(" +
        "  SELECT * FROM dbo.MyFunction() CTX WHERE ISNULL(T.MyOtherId, -1) = CTX.MyOtherId" +
        ")";
    da.SelectCommand = new SqlCommand(sql, cn);

    var ds = new DataSet();
    da.FillSchema(ds, SchemaType.Source);
    //There no table in the DataSet!
}
catch (Exception ex)
{
    MessageBox.Show("Error " + ex.Message);
}
finally
{
    cn.Close();
}

Что-то изменилось в MS SQL 2017?Или, может быть, я что-то не так делаю?

РЕДАКТИРОВАТЬ 1: Проблема исчезает, когда я удаляю условие EXISTS из запроса.Я думаю, что вызов функции может быть причиной.

РЕДАКТИРОВАТЬ 2: Когда я упрощаю запрос до:

var sql = "SELECT * FROM dbo.MyFunction()";

Все еще не работает ... Вы можете задаться вопросомчто MyFunction в SQL делает.Это функция таблицы с несколькими операторами:

CREATE FUNCTION dbo.MyFunction ()
RETURNS @RESULT TABLE 
(
    ID BIGINT NOT NULL,
    NAME VARCHAR(50),
    CODE VARCHAR(50)
)
AS
BEGIN
    INSERT INTO @RESULT VALUES(1, 'Name', 'NAME')
RETURN 
END
GO

Когда я переписываю функцию таблицы с несколькими инструкциями в Inline-Statement, она работает.Я знаю, что это не лучший способ получения схемы в .NET ... но есть идеи, почему не работают функции с несколькими утверждениями?

1 Ответ

0 голосов
/ 04 декабря 2018

Это происходит потому, что SQL Server 2017 не возвращает метаданные, когда SELECT * FROM dbo.MyFunction() выполняется в SET FMTONLY ON, который по-прежнему используется ADO.NET для получения метаданных.Это устарело, и sp_describe_first_result_set работает правильно для этого случая, но это все еще не причина для сбоя SQL Server 2017.Это было зарегистрировано как ошибка .

Предположение: эта ошибка могла быть введена как побочный эффект новой функции выполнения с чередованием , которая изменяет способ выполнения этих функций.Это подтверждается наблюдением, что оно исчезает, если уровень совместимости базы данных снижается до 130, что отключает это (среди прочего).Мне не известен флаг трассировки, который отключает только чередованное выполнение, которое можно использовать для проверки этого.

Существует своего рода обходной путь: set fmtonly on; exec ('select * from dbo.MyFunction()'); set fmtonly off вернет метаданные даже на уровне 140 компаса, поэтомувыборка метаданных запроса с использованием EXEC все равно будет работать.В приведенном выше примере

var sql = "EXEC ('SELECT * FROM dbo.MyFunction()')";

должен возвращать результаты.

...