【发布时间】:2015-12-16 00:48:24
【问题描述】:
我收到错误“File.exe 中发生类型初始化异常;File.Mod2 的类型初始化程序引发异常。”然而,异常的断点在 Mod1 中——顺便说一句,这里没有声明任何内容,Locals 窗口中没有任何内容,也没有要调试的内容......。
我认为这可能与我是在一个模块中声明类型 SqlDataConnection 还是在每个模块中单独声明类型有关,或者我是否在一个模块、每个模块、每个需要的函数中或在一个模块中全局分配 db.GetDataContext函数,然后将其向上传递/传递。但是移动声明并没有帮助。 (过去我很少遇到此错误,但它会自行修复。我忘记了,这太罕见了,我会点击继续。或者我会重新开始,并且在运行时不接触 SQL Server。)
此代码运行了数周,一次可以运行数天并上传 5 亿多条结果。我一直在修改,但我认为我没有触及 Type Provider 或数据库部分中的任何内容。
最后一点:我可以精确定位在迭代中,在进行了一些侦探工作之后引发异常的确切位置。如前所述,调试器在 Mod1 中的一行出现异常中断。但是,如果我遍历迭代,则在 Mod2 中“IDList |> List.iter (fun ID -> GetDataLists ID |> IterateParams ID paramLists)”中的第一个 ID 完成后中断。中断发生在 Mod4 中的最后一个 UpLoad 结果之后,此时代码应返回到 Mod2 以获取下一个 ID,但改为在 Mod1 中中断,即第一个最抽象的调用。最后,请注意错误消息表明异常是在 Mod2 中引发的——即使中断是在 Mod1 中。 (而且我不能从 Mod4 跳到 Mod2 来检查异常条件——它会从 Mod4 跳到 Mod1。)
编辑*** 我弄错了一个细节。中断不会从 Mod4 跳转到 Mod1。 Mod4 确实返回到 Mod2。如果我小心翼翼,流程会从 Mod4 中的最后一次上传(成功)返回到 Mod2 中的 AsyncSeries。然后从 Mod2 中的 AsyncSeries 下一步是到 Mod1 中的一行。
这里是抽象代码,只是为了说明流程,并附有异常注释。
namespace MyNameSpace
module Mod4 = //type provider is used here
let UpLoadOneResult ID result = ... //****Last result of 1st ID uploads.
//Exception then in Mod1--instead of iterating in Mod2.
let UploadResults ID resultsList =
resultsList |> List.iter (fun r -> UploadOneResult ID r)
module Mod3 = //type provider is used here
let rec SolveResults ID kList mList rev resultList (x, y, z, w) = ...
SolveResults ID kList.Tail mList.Tail newResultList (x, y, z, w)
module Mod2 =
type dbSchema1 = Microsoft.FSharp.Data.TypeProviders.
SqlDataConnection<"Data Source=DESKTOP-55M3AJ5\SQLEXPRESS;
Initial Catalog=Data;Integrated Security=True;
MultipleActiveResultSets=True;">
//I omit this from example modules above, but they do have
//dbSchema2, etc.
let GetParamLists = ... //this func just hard coded. my user interface for now.
(xList, yList, zList, wList)
let GetDataLists ID =
let db1 = dbSchema1.GetDataContext() // "use"? "new"? () as argument?
let kList = query { for row in db1.Data ... } |> Seq.toList
let mList = query { for row in db1.Data ... } |> Seq.toList
(kList, mList)
let IterateParams ID (xList, yList, zList, wList) (kList, mList) =
let MakeParamCombos xList yList zList wList =
[for x in xList do
for y in yList do
for z in zList do
for w in wList do
yield (x, y, z, w)]
let AsyncSeries (x, y, z, w) = async {
return SolveResults ID kList mList [] (x, y, z, w)
|> UpLdResults ID }
MakeParamCombos xList yList zList wList
|> List.map AsyncSeries
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
let CalcResults =
let db1 = dbSchema1.GetDataContext()
let paramLists = GetParamLists
let IDList = query { for row in db1.Data ... } |> Seq.toList
IDList |> List.iter (fun ID -> GetDataLists ID |> IterateParams ID paramLists )
//*** the first ID run completes. Code fails to return here for 2nd ID.
()
module Mod1 =
[<EntryPoint>]
let main argv =
CalcResults |> ignore //**ERROR point, on second iteration of "IDList |> List.iter ... "
0
【问题讨论】:
-
在 Mod2 中,在决定性的“IDList |> List.iter”中,IDlist 以 int list 类型给出,GetDataLists 的参数是 int 类型。当我在第一次通过时在这里休息时,IDList 在 Locals 窗口中看起来不错。
-
Big "hmmmm" 这里:如果我注释掉定义 IDList 的查询并硬编码一个 ID 列表: 1. 它在类似 [4; 6; 10个; 12]。但它在 [1; 2; 3; 4]。并且 ID 1 也是查询中的第一个,导致中断。所以我想这可能是数据中的一些奇怪的东西。但是由于这个异常的性质是跳转到错误的模块,而在 Locals 中什么都没有——这就像 1980 年代的调试,或者更糟,现在。
-
但是,如果在声明 SQL 数据连接类型和 GetDataContext 分配的位置方面有任何最佳实践可遵循——这可能会有所帮助,并且在任何情况下都会非常感激。
-
仅供参考:ID 1 的最后一行,之后发生异常是“db3.DataContext.ExecuteCommand(@"INSERT INTO Data.dbo. ...”,在 Mod4 中。让我确认这条线实际上是成功还是失败。它在“try”块中,“with | exn -> ()”。
-
现在我看到了我草率错过的 Mod2 的回归,也许我可以从那里的当地人那里得到一些东西。
标签: asynchronous parallel-processing f# type-providers typeinitializeexception