Сохраненная процедура для пути xml - заказ не работает

Я пытаюсь вытащить записи из базы данных с необязательным порядком. Для этого я создал хранимую процедуру (несколько столбцов для удобства чтения):

CREATE PROCEDURE [dbo].[sp_VendorOverview] (@sortCol nvarchar(50)=NULL)

AS

BEGIN

    SET NOCOUNT ON;
    select v.Vid, s.Salutation, v.LastName, CONVERT(varchar(100), CAST(v.VAT AS decimal(38,0))) AS VAT
    from vendors v
    inner join Salutations s
    on v.salutation=s.anrede

    order by
        CASE WHEN @sortCol='LastName' THEN v.LastName
            WHEN @sortCol='FirstName' THEN v.FirstName
            ELSE NULL
        END,
        CASE WHEN @sortCol ='VendorNumber' THEN v.VendorNumber
            ELSE v.Vid
        END
    for xml path('VendorBasic'), root('Vendors')
END

При запуске этого sp в SSMS все в порядке, результаты соответствуют ожиданиям. Однако это не так, когда вы пытаетесь прочитать это из приложения C # следующим образом:

var vendoren = new List<VendorBasic>();

using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["Vendor"].ConnectionString))
{
    var xml = string.Empty;
    con.Open();
    using (var cmd = new SqlCommand("dbo.sp_VendorOverview", con))
    {
        if (!string.IsNullOrEmpty(orderby))
            cmd.Parameters.AddWithValue("@sortCol", orderby);

        using (XmlReader idr = cmd.ExecuteXmlReader())
        {
            if (idr.Read())
            {
                xml = idr.ReadOuterXml();
            }
            idr.Close();
        }
        con.Close();
    }
    if (xml != string.Empty)
    {
        XmlRootAttribute xRoot = new XmlRootAttribute
        {
            ElementName = "Vendors",
            IsNullable = true
        };
        var engine = new XmlSerializer(typeof(List<VendorBasic>), xRoot);
        vendoren = (List<VendorBasic>)engine.Deserialize(new StringReader(xml));
    }
}

Десериализация работает нормально, для класса VendorBasic установлен атрибут XmlRoot. Я получаю результаты. Они просто никогда не заказываются ничем, кроме Вида. Я установил точку останова, чтобы проверить, правильно ли применен параметр, если я хочу упорядочить по любому другому столбцу. Это:

введите здесь описание изображения

Я что-то упускаю? Я делаю что-то неправильно?


person LocEngineer    schedule 17.10.2017    source источник
comment
Почему у вас есть два выражения case в предложении order by? одно выражение case должно подойти для этого....   -  person Zohar Peled    schedule 17.10.2017
comment
@ZoharPeled Мне нужно два, потому что они относятся к двум разным типам полей: nvarchar и int. СЛУЧАЙ, КОГДА выражения пытаются унифицировать типы полей до самого высокого порядка, что означает, что в этом случае он попытается преобразовать LastName в тип int, если у меня есть, например. VendorNumber также в том же блоке CASE. Пришлось учиться этому на собственном горьком опыте. Вам нужен один блок CASE для каждого типа поля, с которым вы хотите работать. :-)   -  person LocEngineer    schedule 17.10.2017
comment
Может, тебе стоит сделать cmd.CommandType = CommandType.StoredProcedure;?   -  person Evk    schedule 17.10.2017
comment
@Evk Сукин сын!! Это было действительно все, что нужно! Раскрасьте меня в шоке - и, пожалуйста, напишите как ответ. :-)   -  person LocEngineer    schedule 17.10.2017


Ответы (1)


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

cmd.CommandType = CommandType.StoredProcedure;

Без этого он будет игнорировать все ваши параметры и выполнять процедуру с параметрами по умолчанию (в данном случае null). Дополнительную информацию об этом можно найти в этом вопросе: При выполнении хранимой процедуры в чем преимущество использования CommandType.StoredProcedure по сравнению с использованием CommandType. Текст?.

person Evk    schedule 17.10.2017