Потокобезопасные выражения запросов F#
У меня есть набор функций, которые с помощью FSharp.Data.TypeProviders делают несколько обращений к базе данных через sql для получения данных.
Код выглядит следующим образом:
let query_one (firstName:string) (lastName:string) =
query { for a in db.Names do
where (a.firstname = FirstName && a.secondname = LastName)
select a } |> Seq.last
let query_two (jobTitle:string) =
query { for a in db.Jobs do
where (a.jobId = jobTitle)
select a } |> Seq.last
let detailsList = new List<('a*'b)>()
let queries =
workerDetails
|> Array.Parallel.map (fun (firstn, lastn, jobt) ->
let j1 = query_one firstn lastn
let j2 = query_two jobt
detailsList.add (j1,j2) )
Когда я запускаю это, я получаю следующее:
Первое случайное исключение типа "System.ArgumentException" произошло в FSharp.Core.dll
Дополнительная информация: элемент с таким же ключом уже добавлен.
Чтобы быть более точным:
System.ArgumentException: элемент с тем же ключом уже был добавлен. в Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter.EvaluateQuotation(FSharpExpr e) в Microsoft.FSharp.Linq.QueryModule.EvalNonNestedInner(CanEliminate canElim, FSharpExpr в Microsoft.FSharp.Linq.QueryModule.clo@1737-1.Microsoft-FSharp-Linq-ForwardDeclarations-IQueryMethods-Execute[a,b](FSharpExpr`1) ... ... в Microsoft.FSharp.Collections.ArrayModule.Parallel.Map@714-3.Invoke(Int32 obj) в System.Threading.Tasks.Parallel.<> C__DisplayClassf`1.b__c() в System.Threading.Tasks.Task.InnerInvoke() в System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask) в System.Threading.Tasks.Task.<> C__DisplayClass11.b__10(Object param0) <---
Я также попытался запустить его из C# с помощью Parallel.For().. Я, вероятно, пропустил что-то основное. Есть ли простой способ сделать функцию поточно-ориентированной? или выражение запроса?
Спасибо за помощь!
Возможный вариант разрешения: Когда я включил вызов для контекста базы данных в функцию, разрешил исключение parralel. Такие как:
let query_one (firstName:string) (lastName:string) =
let db = temp_schema.GetDataContext()
query { for a in db.Names do
where (a.firstname = FirstName && a.secondname = LastName)
select a } |> Seq.last