f # выражение запроса для получения элементов по идентификатору в списке - PullRequest
0 голосов
/ 07 июня 2018

Я использую f # для обновления БД из файла csv, поэтому я использую Fsharp.Data для его анализа, и он работает хорошо, как задумано, а затем SqlProvider для фактического обновления.
Итак, я получаю list элементов из моего CSV, и одно из полей является идентификатором таблицы, которую я собираюсь обновить.Я пришел из ac # background, поэтому с помощью LINQ я мог бы сделать что-то вроде этого:

var results = context.MyTable.Where(m => myList.Contains(m.Identifier))

, и это дало бы мне строки, которые я ищу.Я попытался сделать это

query {
    for m in ctx.Dbo.MyTable do
    where (List.contains m.Identifier myList)
    select m
}

и получил эту ошибку во время выполнения:

System.InvalidOperationException: переменная 'm' типа 'FSharp.Data.Sql.Common.SqlEntity'ссылка из области действия' ', но не определена
в Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation (FSharpExpr e)
в Microsoft.FSharp.Linq.QueryModule.EvalNonNestedInner)
в Microsoft.FSharp.Linq.QueryModule.clo@1727-1.Microsoft-FSharp-Linq-ForwardDeclarations-IQueryMethods-Execute [a, b] (FSharpExpr`1 q)
at. $ FSI_0006.main@ ()
Остановлен из-за ошибки

, затем попробовал следующее

query {
    for m in ctx.Dbo.MyTable do
    for id in myList do
    where (id = m.Identifier)
    select m
}

и получил это во время компиляции:

myScript.fsx (291,30): ошибка FS0001: тип 'список строк' не совместим с типом 'System.Linq.IQueryable'

Я уверен, что это можно сделать, я быхотел бы знать, что я делаю не так

Как правильно поступитьэто?
Что я предполагаю, что это явно неправильно?

Обновление

Я только что последовал за ответом Аарона, вот как теперь выглядит мой код, по крайней мере, соответствующая часть:

let ctx = Sql.GetDataContext();

let getZipCodes (zipcodes: string list) = 
    query {
        for zc in ctx.CleanZipCodes do
        for id in zipcodes do
        where (id = zc.ZipCode)
        select zc
    }
    |> Seq.toList

и теперь я получаю эту ошибку:

System.Data.EntityCommandExecutionException: Произошла ошибка при выполнении определения команды.Смотрите внутреннее исключение для деталей.--->

System.Data.SqlClient.SqlException: некоторая часть вашего оператора SQL вложена слишком глубоко.Перепишите запрос или разбейте его на более мелкие запросы.в System.Data.SqlClient.SqlConnection.OnError (исключение SqlException, логическое breakConnection, Action'1 wrapCloseInAction)
в System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (TdsParserStateObneleSignLoneLockSignLoneLockLoneLoneLoneLoneLoClayOneLockOjLoneLoClayOneLockOllSignObjectObLeO).Data.SqlClient.TdsParser.TryRun (RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject.SqlClient.SqlDataReader.get_MetaData ()
в System.Data.SqlClient.SqlCommand.FinishExecuteReader (SqlDataReader Д.С., RunBehavior runBehavior, String resetOptionsString, Boolean IsInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
в System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (CommandBehavior cmdBehavior, RunBehavior runBehavior, логический returnStream, логический асинхронный, InТайм-аут t32, Задача и задание, логическое значение asyncWrite, логическое значение inRetry, SqlDataReader ds, логическое значение descriptionParameterEncryptionRequest)
в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior, метод возврата к исходному объекту, метод возврата к исходному объекту, метод возврата к исходному объекту, метод возврата к исходному объекту, метод возврата к исходному объекту, метод возврата к объекту, метод возврата к объектутайм-аут, задача и задача, логический и используемый кэш, логический asyncWrite, логическое inRetry)
в System.Data.SqlClient.SqlCommand.RunExecuteReader (CommandBehavior cmdBehavior, RunBehavior runBehavior, метод Boolean.SqlCommand.ExecuteReader (поведение CommandBehavior, метод String)
в System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, поведение CommandBehavior)

--- трассировка стека внутренних исключений ---*

в System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands (EntityCommand entityCommand, поведение CommandBehavior)
в System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute * параметр контекстной системы TRESultType62.Data.Objects.ObjectQuery'1.GetResults (Nullable'1 forMergeOption) в System.Data.Objects.ObjectQuery'1.System.Collections.Generic.IEnumerable.GetEnumerator ()
в Microsoft.FSharp.Collections.Seq.ToList [T] (источник IEnumerable'1)
at. $ FSI_0006.main @ ()

1 Ответ

0 голосов
/ 07 июня 2018

Ошибка во втором примере, похоже, связана с LINQ to SQL.Вы можете обойти это, используя поставщика типа сущности SQL, который называется SqlEntityConnection в поставщиках встроенного типа:

#r "System.Data.Entity"
#r "FSharp.Data.TypeProviders"

open Microsoft.FSharp.Data.TypeProviders

type SqlDb = SqlEntityConnection<"...">

let context = SqlDb.GetDataContext()

let myList = [...]

query {
    for record in context.MyTable do
    for id in myList do
    where (id = record.Identifier)
    select record
} |> Seq.toList
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...