Присоединение расширенных свойств к набору результатов хранимой процедуры

Я пытаюсь прикрепить метаданные к результирующему набору хранимой процедуры. Процедура вернет таблицу либо в результате запроса SELECT, либо временную таблицу, созданную самой процедурой. Я хотел бы украсить его столбцы дополнительной информацией, чтобы как бы эмулировать атрибуты .NET. Затем при выполнении процедуры с ADO.NET я хочу оценить эти метаданные.

Насколько я могу судить, это не может быть легко сделано. Возможно, я мог бы обойти это, создав глобальную временную таблицу (префикс ##), а затем вручную прикрепив к ней расширенные свойства в tempdb. Любые идеи?


person Sören Kuklau    schedule 08.07.2014    source источник
comment
Насколько я могу судить, это вообще невозможно.   -  person TomTom    schedule 25.07.2014


Ответы (2)


Почему бы не вернуть 2 набора результатов из SP? Один из них — это фактический набор результатов, который у вас есть сейчас, а другой — это метаданные.

Таблица метаданных может быть табличной переменной, созданной в SP, со следующей структурой:

DECLARE @ResultsMetadata AS TABLE
(
  Id INT NOT NULL IDENTITY(1,1),
  ColumnName VARCHAR(128) NOT NULL,
  ColumnMetadata VARCHAR(128) NOT NULL
)

Вы можете прочитать это в том, что я предполагаю, это CLR (из-за тега). Легко читать несколько наборов результатов с помощью SqlDataReader. Если вам необходимо дополнительно обработать результаты также в SQL, то, возможно, вы можете переключиться на вывод XML с двумя элементами верхнего уровня (основной набор результатов и метаданные).

ИЗМЕНИТЬ

На самом деле только что заметил, что вы читаете это с помощью ADO.NET, поэтому у вас не должно быть проблем с несколькими наборами результатов. Вы можете использовать SqlDataReader.NextResult. чтобы перейти ко второму набору результатов (метаданные).

person Marcel N.    schedule 25.07.2014
comment
Да, это хак, который я имел в виду, но хотел избежать. Я, пожалуй, соглашусь с этим, спасибо. - person Sören Kuklau; 01.08.2014
comment
@SörenKuklau: Да :), я думаю, что это можно назвать взломом, если посмотреть на это таким образом. Однако, когда вы хотите исключить некоторые круговые поездки, это на самом деле идеально. - person Marcel N.; 01.08.2014

Предлагаемый метод 1:

сначала создайте тип метаданных:

CREATE TYPE MetaData AS TABLE
(
  Name VARCHAR(128) NOT NULL,
  Property NVARCHAR(Max)
)

В каждой хранимой процедуре возвращайте свои метаданные после набора результатов вашей хранимой процедуры:

CREATE PROCEDURE YourProcedure 
AS BEGIN
    --FIRST Result Set
    --Your Stored Procedure code here
    ...


    --Second Result Set
    DECLARE @MetaData dbo.MetaData 
    INSERT INTO @MetaData(Name, Property)VALUES(...)
    SELECT * FROM @MetaData
END

Вы можете прочитать свой набор результатов в коде отдельно. следующий код представляет собой код C# для получения нескольких наборов результатов из одной хранимой процедуры.

SqlConnection oConn = null;
DataSet dsReturn = null;
try
{
    getConnection(ref oConn, 1);

    using (SqlStoredProcedure sspObj = new SqlStoredProcedure("dbo.YourStoredProcedure", oConn, CommandType.StoredProcedure))
    {
        sspObj.AddParameterWithValue("@Parameter", SqlDbType.Int, Parametervalue, ParameterDirection.Input, type);
        dsReturn = sspObj.ExecuteDataSet();
        //You don't need Dispose() - because the using will do that on sspObj
    }

    closeConnection(ref oConn);
}
catch (Exception xObj)
{
    dsReturn = new DataSet("Empty");
}

В приведенном выше коде dsReturn.Tables[0] — это результирующий набор вашей хранимой процедуры, а dsReturn.Tables[1] — результирующий набор метаданных вашей хранимой процедуры.

Предлагаемый метод 2:

Добавьте все метаданные, которые хотят расширить свойство вашей хранимой процедуры:

EXEC sys.sp_addextendedproperty @name=N'MetaDataColumn1', @value=N'value1' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'YourProcedure'
GO
EXEC sys.sp_addextendedproperty @name=N'MetaDataColumn2', @value=N'value2' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'PROCEDURE',@level1name=N'YourProcedure'
GO

После запроса верните метаданные вашей хранимой процедуры:

SELECT ep.name, ep.value
FROM sys.extended_properties ep
INNER JOIN sys.procedures p ON p.object_id = ep.major_id
WHERE p.name = 'YourProcedure'
    AND ep.name LIKE 'MetaData%'

вы можете выполнить вышеуказанный запрос из своего кода (пример С#):

connetionString = "Data Source=ServerName;Initial Catalog=DatabaseName;User ID=UserName;Password=Password";
sql = "AboveQuery";
sqlCnn = new SqlConnection(connetionString);
sqlCnn.Open();
sqlCmd = new SqlCommand(sql, sqlCnn);
SqlDataReader sqlReader = sqlCmd.ExecuteReader();
person mehdi lotfi    schedule 26.07.2014