Как зафиксировать набор результатов хранимой процедуры с помощью динамического выбора (sp_executesql) в отчете RDLC

Мне нужно получить набор результатов, который сгенерирует хранимую процедуру с динамическим запросом (sp_executesql), проблема в том, что при определении DataSource, которая в данном случае будет хранимой процедурой, она не возвращает ни одного столбца. в итоге тем же от мастера DataSource.

У меня есть еще один отчет (rdlc) о том, что хранимая процедура с DataSource не является динамическим запросом, который возвращает набор результатов.

Я думал о том, чтобы иметь возможность записать инструкцию, которая решает sp_executesql в переменной (@instruction), а затем взять ее и выполнить снова как Select из мастера настройки запросов TableAdapter.

ALTER PROCEDURE dbo.StoredProcedureA 
    @xmlParameter XML 
AS
BEGIN
    SET NOCOUNT ON 

    DECLARE @DespachoR  VARCHAR(100),
    @DespachoRBEsta TINYINT,
    @PaisOrigenR VARCHAR(100),
    @PaisOrigenBEsta TINYINT,
    @Estampilla INTEGER,
    @DesdeFecha VARCHAR(10),
    @HastaFecha VARCHAR(10),
    @desfecha datetime,
    @hasfecha datetime,
    @strWhereRan VARCHAR(MAX),
    @strWhere VARCHAR(MAX),


    @seteos nvarchar(200),
    @instruccion nvarchar(max),
    @instruccion2 nvarchar(max),
    @texto varchar(max),
    @columna varchar(100),
    @tipodato varchar(50)


    If @xmlParametros is not null
    begin

DECLARE @xml TABLE ( identidad integer IDENTITY (1,1) not null, tipo char(1) not null, columna varchar(30) not null, campoxml varchar(1000) not null, 
    tipodato varchar(50) not null, nulo tinyint null)

INSERT @xml (columna, tipo, campoxml, tipodato, nulo)


SELECT '@DespachoR', 'E', '(/Parameters/DESPACHOR/text())[1]', 'varchar(100)', null 
UNION ALL
SELECT '@DespachoRBEsta', 'E', '(/Parameters/DESPACHORBESTA/text())[1]', 'tinyint', null 
UNION ALL
SELECT '@PaisOrigenR', 'E', '(/Parameters/PAISORIGENR/text())[1]', 'varchar(100)', null 
UNION ALL
SELECT '@PaisOrigenBEsta', 'E', '(/Parameters/PAISORIGENRBESTA/text())[1]', 'tinyint', null 
UNION ALL
SELECT '@Estampilla', 'E', '(/Parameters/ESTAMPILLA/text())[1]', 'integer', null 
UNION ALL
SELECT '@DesdeFecha', 'E', '(/Parameters/DESDEFECHA/text())[1]', 'varchar(10)', null 
UNION ALL
SELECT '@HastaFecha', 'E', '(/Parameters/HASTAFECHA/text())[1]', 'varchar(10)', null 


SELECT @seteos = 'SET ANSI_NULLS ON
        SET QUOTED_IDENTIFIER ON
        SET CONCAT_NULL_YIELDS_NULL ON
        SET ANSI_PADDING ON
        SET ANSI_WARNINGS ON
        SET ARITHABORT ON
        SET NUMERIC_ROUNDABORT OFF '
select @instruccion =null, @instruccion2 = N'@xmlParametros xml'

DECLARE INSTRUCCION INSENSITIVE CURSOR FOR
SELECT columna, "@xmlParametros.value('" + campoxml + "', '" + tipodato + "')", tipodato
FROM @xml
WHERE tipo='E'
ORDER BY identidad  

OPEN INSTRUCCION
FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato

WHILE (@@FETCH_STATUS <> -1)
 begin
    If @instruccion is not null
        SELECT @instruccion  = @instruccion + ', '

    SELECT @instruccion  = @instruccion + @columna + '=' + @texto, @instruccion2 = @instruccion2 + ', ' + @columna + ' ' + @tipodato + ' OUTPUT'

    FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato
 end

CLOSE INSTRUCCION
DEALLOCATE INSTRUCCION

SELECT @instruccion = @seteos + N'SELECT ' + @instruccion 

--end
                    --@instruccion: SETEOS
exec sp_executesql  @instruccion, @instruccion2,@xmlParametros=@xmlParametros, @DespachoR=@DespachoR OUTPUT,
                    @DespachoRBEsta=@DespachoRBEsta OUTPUT, @PaisOrigenR=@PaisOrigenR OUTPUT, @PaisOrigenBEsta=@PaisOrigenBEsta OUTPUT, @Estampilla=@Estampilla OUTPUT,
                    @DesdeFecha=@DesdeFecha OUTPUT, @HastaFecha=@HastaFecha OUTPUT

IF @DespachoR is not null
 begin
    EXEC sp_armo_rango @DespachoR, 'D.Despacho', @DespachoRBEsta, 0, @strWhereRan OUTPUT

    IF @strWhereRan is not null
        Set @strWhere = @strWhere + " AND " + rtrim(@strWhereRan)


 end

IF @PaisOrigenR is not null
begin
     EXEC sp_armo_rango @PaisOrigenR, 'D.Paisorigen', @PaisOrigenBEsta, 0, @strWhereRan OUTPUT
     IF @strWhereRan is not null
          Set  @strWhere  =  @strWhere  + " AND " + rtrim(@strWhereRan)
end

IF @Estampilla is not null
     --Esto determina que se listen los despachos que tienen la estampilla indicada, los despachos así determinados se listan completos, 
     --es decir, con todos los rangos de estampillas.
     Set @strWhere = @strWhere + ' AND 0<>(SELECT count(*) FROM Despachosestampillas De1 (nolock)
                          WHERE     De1.Despacho=D.Despacho AND 
                               De1.Hasta >=@estampilla AND De1.Desde <= @estampilla )'

IF @DesdeFecha is not null
begin
    select @desfecha=convert(datetime, @desdefecha, 103)

     Set  @strWhere  =  @strWhere  + ' AND  D.Fecha >=@desfecha'
 end

IF @HastaFecha is not NULL
    begin
    select @hasfecha=convert(datetime, @HastaFecha, 103)

     Set @strWhere = @strWhere + ' AND  D.Fecha <=@hasfecha'
 end


Set @instruccion  = N'SELECT D.Despacho, D.Fecha as FechaD, D.Aduana, D.Paisorigen as Pais, D.Garantia, 
                CASE WHEN D.TipoGarantia="E" THEN "Efectivo" 
                     WHEN D.TipoGarantia="C" THEN "Caución" 
                     WHEN D.TipoGarantia="M" THEN "Mixto" 
                     ELSE null END as Tipo, 
                D.Efectivo, D.FechaGarantia as Fecha, D.Compania, D.Poliza, D.FechavtoGarantia as Fechavto, D.Monto as Importe, 
                De.Desde, De.Hasta, convert(varchar(254), D.Observacion) as Observacion 
          FROM Despachos D (nolock)
                LEFT JOIN Despachosestampillas De (nolock) ON D.Despacho=De.Despacho
          WHERE 1=1 ' +  @strWhere + '
          ORDER BY D.Despacho, De.Desde'


          exec sp_executesql    @instruccion, N'@estampilla integer, @desfecha datetime, @hasfecha datetime', @estampilla=@estampilla, @desfecha=@desfecha, @hasfecha=@hasfecha


    end



    END

ALTER PROCEDURE dbo.StoredProcedureB    
    @xmlParametros XML
AS
BEGIN
    SET NOCOUNT ON;
    SET CONCAT_NULL_YIELDS_NULL OFF
    SET ANSI_NULLS OFF
    SET QUOTED_IDENTIFIER OFF
    SET NOCOUNT ON

    DECLARE @Sistema CHAR(1),
@Caratula tinyint,
@FormatoQRP VARCHAR(12),

@seteos NVARCHAR(200),
@instruccion NVARCHAR(max),
@instruccion2 NVARCHAR(max),
@texto VARCHAR(max),
@columna VARCHAR(100),
@tipodato VARCHAR(50)

IF @xmlParametros is not null
 BEGIN

    DECLARE @xml TABLE ( identidad integer IDENTITY (1,1) not null, tipo char(1) not null, columna varchar(30) not null, campoxml varchar(1000) not null, 
        tipodato varchar(50) not null, nulo tinyint null)

    INSERT @xml (columna, tipo, campoxml, tipodato, nulo)

    --      PARAMETRO    DIF      RUTA_DEL_NODO                         TIPO_DATO_NODO  NULO

    SELECT '@Sistema', 'E', '(/Parameters/SISTEMA)[1]', 'char(1)', null 
    UNION ALL
    SELECT '@Caratula', 'E', '(/Parameters/CARATULA)[1]', 'tinyint', null 
    UNION ALL
    SELECT '@FormatoQRP', 'E', '(/Parameters/FORMATOQRP)[1]', 'varchar(12)', null 
    --SELECT*FROM @xml

    --SETEOS SUMADOS A LA INSTRUCCION GRAL.
    SELECT @seteos = 'SET ANSI_NULLS ON
            SET QUOTED_IDENTIFIER ON
            SET CONCAT_NULL_YIELDS_NULL ON
            SET ANSI_PADDING ON
            SET ANSI_WARNINGS ON
            SET ARITHABORT ON
            SET NUMERIC_ROUNDABORT OFF '
    select @instruccion =null, @instruccion2 = N'@xmlParametros xml'

    --DECLARA CURSOR PARA RECORRER TABLA DECLARADA
    DECLARE INSTRUCCION INSENSITIVE CURSOR FOR
    SELECT columna, "@xmlParametros.value('" + campoxml + "', '" + tipodato + "')", tipodato
    FROM @xml
    WHERE tipo='E'
    ORDER BY identidad  

    OPEN INSTRUCCION
    FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato

    WHILE (@@FETCH_STATUS <> -1)
     BEGIN
        If @instruccion is not null
            SELECT @instruccion  = @instruccion + ', '

        SELECT @instruccion  = @instruccion + @columna + '=' + @texto, @instruccion2 = @instruccion2 + ', ' + @columna + ' ' + @tipodato + ' OUTPUT'

        FETCH NEXT FROM INSTRUCCION INTO @columna, @texto, @tipodato
     END

    CLOSE INSTRUCCION
    DEALLOCATE INSTRUCCION

    SELECT @instruccion = @seteos + N'SELECT ' + @instruccion 


    exec sp_executesql  @instruccion, @instruccion2,@xmlParametros=@xmlParametros,
                        @Sistema=@Sistema OUTPUT, @Caratula=@Caratula OUTPUT,
                        @FormatoQRP=@FormatoQRP OUTPUT
 END


IF @Sistema != 'C'
    SELECT CENPREFI, CODCEN, NOMBRE, ADMNEGOCIOS
    FROM dbo.CENTROSAP  (NOLOCK)
    ORDER BY CENPREFI
ELSE
    SELECT CENPREFI, CODCEN, NOMBRE
    FROM dbo.CENTROSAP  (NOLOCK)
    ORDER BY CENPREFI
END

В обоих случаях необходимо получить результирующий набор для обеспечения DataSource, определенного в отчете RDLC.

Большое спасибо!


person NHCives    schedule 02.01.2019    source источник
comment
Попробуйте добавить USE DataBaseName в запрос. сервер может иметь более одной базы данных, и диспетчер отчетов не знает, к какой базе данных обращаться. Файл RDLC (это текст, который можно открыть с помощью Блокнота) имеет тег CommandText, и вы можете поместить текст команды в SSMS для проверки и убедиться, что он возвращает результаты. Знак «больше» и «меньше» — это html, и их необходимо заменить в SSMS.   -  person jdweng    schedule 02.01.2019
comment
Хороший! В теге CommandText как вы мне указали тот же рисунок следующий: ‹CommandText›/*Local Query*/‹/CommandText› По поводу знаков больше и меньше не могу понять что вы указываете.   -  person NHCives    schedule 02.01.2019
comment
html содержит символы '‹' и '›' вокруг имен элементов, внутренний текст не может содержать эти два символа. Таким образом, внутренний текст html вы используете '' вместо знака больше и '' вместо знака меньше. Внутренним текстом должно быть то, что вы помещаете в комментарии /* Локальный запрос */ Я предполагаю, что вместо комментариев существует реальный оператор SELECT.   -  person jdweng    schedule 02.01.2019
comment
Добавьте туда полный код SP, который я использую, чтобы получить набор результатов. Как я уже указал, неудобство заключается в том, что когда я добавляю набор данных в отчет rdlc, он ничего мне не возвращает.   -  person NHCives    schedule 03.01.2019
comment
Я бы добавил USE в запрос, чтобы убедиться, что он использует правильную базу данных. Я бы проверил файлы журналов, чтобы узнать, сообщает ли база данных о каких-либо ошибках. Я также попытался бы определить, вызываются ли процедуры. Вы можете создать представление для отладки и добавить записи в представление, чтобы вы могли узнать, выполнялись ли процедуры и как далеко выполнялся код.   -  person jdweng    schedule 03.01.2019


Ответы (2)


Параметр WITH RESULT SETS можно использовать для определения метаданных для хранимой процедуры, когда входные параметры не возвращают никаких результатов. Сделав это, вы определите столбцы, которые будут использоваться для результатов, и в отчете будут работать столбцы независимо от используемого параметра. Пример этого следует. Кроме того, нужна ли подсказка NOLOCK? Среди прочего, это может привести к противоречивым результатам.

EXEC YourDatabase.YourSchema.YourSP @ParameterName
WITH RESULT SETS 
(
  (
    ColumnA INT,
    ColumnB VARCHAR(100),
    ColumnC VARCHAR(100)
  )
)
person userfl89    schedule 02.01.2019
comment
@NHCives Я не совсем понял твой комментарий. Это решило вашу проблему? - person userfl89; 04.01.2019
comment
Добрый день! Я не думаю, что проблема заключается в типе данных каждого столбца, который составляет ResultSet, а скорее в том, что он не распознает хранимую процедуру как объект, который возвращает строки, как если бы случай SP, у которого есть Select - person NHCives; 04.01.2019
comment
Параметр WITH RESULT SETS определяет возвращаемые столбцы. Типы данных включены, чтобы связать правильные метаданные. Это похоже на определение того, из каких столбцов будет состоять Select. - person userfl89; 04.01.2019

Я только что создал соединение, команду sql и адаптер данных, чтобы получить набор результатов. Не могли бы вы сказать мне, если это нормально:

SqlConnection conexionSQL = new SqlConnection("Data Source=SRVDESARROLLO7\\BASCS;Initial Catalog=BASCSREPORT;Integrated Security=True");
conexionSQL.Open();
string stringCommand = "dbo.XXX_SP_REPORTING_SERVICES_DESPACHOS";
SqlCommand comandoSQL = new SqlCommand(stringCommand, conexionSQL);
comandoSQL.CommandType = CommandType.StoredProcedure;
comandoSQL.Parameters.AddWithValue("@xmlParametros", SqlDbType.Xml).Value = parametrosXML.ToString();
SqlDataAdapter da = new SqlDataAdapter(comandoSQL.ToString(), conexionSQL);
da.SelectCommand = comandoSQL;
BASCSREPORTDataSet dataSet1 = new BASCSREPORTDataSet();
da.Fill(dataSet1, dataSet1.Tables[0].TableName);
ReportDataSource rds = new ReportDataSource("XXX_SP_REPORTING_SERVICES_DESPACHOS", dataSet1.Tables[0]);
this.reportViewer1.LocalReport.DataSources.Clear();
this.reportViewer1.LocalReport.DataSources.Add(rds);
this.reportViewer1.LocalReport.Refresh();
this.reportViewer1.RefreshReport();
person NHCives    schedule 07.01.2019