Именованные параметры с данными fsharp SqlClient

У меня возникли проблемы с компиляцией этого кода при загрузке T-Sql из внешнего файла. Код работает, когда T-Sql вставляется непосредственно в F # как:

 type GetRecentMedia =
        SqlCommandProvider<"DECLARE @MedId NVARCHAR(128);
                            DECLARE @TopN INT;

                            select Top(@TopN) * from media.mediaInfo
                            where MediaId = @MedId",
                            Admin.connectionString, ConfigFile = "Web.config">

Но я получаю эту ошибку при попытке загрузить T-Sql из файла sql:

Execute принимает 0 аргументов, но здесь дается 2.

T-Sql:

DECLARE @MedId NVARCHAR(128);
DECLARE @TopN INT;

select Top(@TopN) * from media.mediaInfo
where MediaId = @MedId

F#:

module internal FeedRecentMedia =

    type GetRecentMedia =
        SqlCommandProvider<"Social\InstagramFeed_Select_GetRecentMedia.sql",
                            Admin.connectionString, ConfigFile = "Web.config">
module MediaTool =

    // get current media
    let rM = new FeedRecentMedia.GetRecentMedia()
    let curMedia = rM.Execute(MedId = "Id", TopN = 1) |> Seq.head

Я протестировал t-sql в студии управления, и он там работает. Я получаю только вышеупомянутую ошибку. Что мне здесь не хватает?


person user1206480    schedule 09.01.2015    source источник
comment
Я сделал обновление. Я обнаружил, что он отлично работает, когда t-sql вставляется непосредственно в F#, но по-прежнему не работает при внешней загрузке.   -  person user1206480    schedule 09.01.2015
comment
Как вы думаете, зачем нужно объявлять переменные в T-SQL?   -  person Dmitry Sevastianov    schedule 10.01.2015
comment
В основном только для тестирования запроса в студии управления. Я оставил декларации только потому, что не думал, что это на что-то повлияет. Должен ли я удалить его полностью?   -  person user1206480    schedule 10.01.2015
comment
Да, я думаю, что это сводит с ума анализатор SQL.   -  person Dmitry Sevastianov    schedule 10.01.2015


Ответы (1)


Это задокументированное ограничение поставщика типа SqlClient. Параметры, которые вы передаете из кода F# в T-SQL, должны быть

  • необъявленный (что может быть проблемой, если тип неоднозначен, например, для числовых типов)
  • используется только один раз

К счастью, один и тот же обходной путь, представленный в документации, решает обе проблемы: вы объявляете переменную, используя внешнюю переменную в качестве параметра. Это также позволяет вам явно аннотировать тип:

type FizzOrBuzz = SqlCommandProvider<"
    DECLARE @x AS INT = @xVal
    SELECT 
        CASE 
            WHEN @x % 3 = 0 AND @x % 5 = 0 THEN 'FizzBuzz' 
            WHEN @x % 3 = 0 THEN 'Fizz' 
            WHEN @x % 5 = 0 THEN 'Buzz' 
            ELSE CONCAT(@x, '') --use concat to avoid nullable column
        END", connectionString>

let fizzOrBuzz = new FizzOrBuzz()
printfn "Answer on interview:\n%A" [ for i = 1 to 100 do yield! fizzOrBuzz.Execute(i) ]
person piaste    schedule 21.08.2015