Asynchronous F#Async-已添加具有相同密钥的项

Asynchronous F#Async-已添加具有相同密钥的项,asynchronous,parallel-processing,f#,Asynchronous,Parallel Processing,F#,我正在f#中尝试一些异步操作,但运气不好。我试图从数据库中抓取记录,并并行地对每个记录执行操作 let IsA1 companyId = query { for comp in db.Company do join cc in db.CC on (comp.CompanyId = int(cc.CompanyId)) join pp in db.PP on (cc.PartId = pp.PartId)

我正在f#中尝试一些异步操作,但运气不好。我试图从数据库中抓取记录,并并行地对每个记录执行操作

let IsA1 companyId = 
    query {   for comp in db.Company do
                join cc in db.CC on (comp.CompanyId = int(cc.CompanyId))
                join pp in db.PP on (cc.PartId = pp.PartId)
                join tl in db.TL on (pp.CompanyId = tl.CompanyId)
                where (comp.CompanyId = companyId)
                select (comp.CompanyId > 0)
          }
          |> Seq.length |> fun len -> len > 0

let IsA2 companyId = 
    query {   for t in db.Title do
                join pp in db.PP on (t.Tid = pp.Tid)
                join comp in db.Company on (pp.CompanyId = comp.CompanyId)
                where (comp.CompanyId = companyId)
                select (comp.CompanyId > 0)
          }
          |> Seq.length |> fun len -> len > 0

let GetAffiliations id = 
    async {
        if (IsA1 id) then return "AffilBBB"
        elif (IsA2 id) then return "AffilCCD"
        else return Unknown
    }

let ProcessCompany (company:dbSchema.ServiceTypes.Company) =
    async {
            let grp = GetAffiliations company.CompanyId
            let result = { Id=company.CompanyId; Name=company.Name; Affiliations=grp; ContactType="ok"; }
            return result
    }

let GetCompanyNames =
    let companies = db.Company |> Seq.distinctBy(fun d -> d.CompanyId)
    companies
    |> Seq.map(fun co -> ProcessCompany co)
    |> Async.Parallel
    |> Async.RunSynchronously
当我运行上述代码时,我得到一个错误:

System.ArgumentException: An item with the same key has already been added.
该错误是由于异步{}内的另一个函数调用导致的:

let grp = GetAffiliations company.CompanyId

我确信这是一个新手问题,但我不确定问题是什么。我甚至尝试在异步{}的内部调用另一个异步调用,并使用
let!grp=(GetAffiliations company.CompanyId)
但这无法解决。

因为两个并发查询共享相同的上下文,当第二个结果添加到相同的上下文时,您会收到一个错误,说明上下文中已经有一个具有相同键的项


为每个查询使用“db”上下文的不同实例应该可以解决您的问题

我是否正确:错误在
GetAffiliations
中?如果是这样,您必须查看/发布它-您确实显示的代码看起来不错-但当然几乎不可能确定,因为我们显然无法运行它-因此以防万一,您可以发布完整的异常(请使用stacktrace)?无论我在async内部调用什么方法,我都会收到错误(当该方法也与db联系时)--我只是举个例子,我实际上调用了异步{}中的两个方法,其中一个给出了相同的错误。对不起,你太快了-我用另一个方法调用更新了这个问题..下面是stacktrace:System.ArgumentException:已经添加了一个具有相同键的项。在Microsoft.FSharp.Control.AsyncBuilderImpl.commit[a](结果
1 res)在Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously[a](取消令牌令牌,FSharpAsync
1计算,FSharpOption
1超时)在Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync
1计算,FSharpOption
1超时,FSharpOption
1取消令牌)位于$FSI_0008.main@)在C:\Script.fsx:第111行中,我怀疑这是因为您使用的是相同的“db”上下文。请尝试为每个查询使用两个不同的上下文实例。对于同一路径上的任何人,请发表评论:我通过提供单独的db上下文修复了此问题。虽然处理速度快了1/3,但我发现使用FSharp.Data.SqlClient而不是Microsoft.FSharp.Data.TypeProviders使代码更快(我测量)和更干净(EF重量级ORM更少,轻量级ORM更简洁)-并且不需要大量的上下文切换。