Asynchronous F#Async-已添加具有相同密钥的项
我正在f#中尝试一些异步操作,但运气不好。我试图从数据库中抓取记录,并并行地对每个记录执行操作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)
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计算,FSharpOption1超时)在Microsoft.FSharp.Control.FSharpAsync.RunSynchronously[T](FSharpAsync
1计算,FSharpOption1超时,FSharpOption
1取消令牌)位于$FSI_0008.main@)在C:\Script.fsx:第111行中,我怀疑这是因为您使用的是相同的“db”上下文。请尝试为每个查询使用两个不同的上下文实例。对于同一路径上的任何人,请发表评论:我通过提供单独的db上下文修复了此问题。虽然处理速度快了1/3,但我发现使用FSharp.Data.SqlClient而不是Microsoft.FSharp.Data.TypeProviders使代码更快(我测量)和更干净(EF重量级ORM更少,轻量级ORM更简洁)-并且不需要大量的上下文切换。