F#SqlProvider无法使用ODBC连接更新数据库DBF文件中的更改

F#SqlProvider无法使用ODBC连接更新数据库DBF文件中的更改,f#,odbc,dbf,dbase,F#,Odbc,Dbf,Dbase,我有以下F#代码 新的错误是: System.Exception:错误-无法更新未更新的实体 有一个主键。(dbo.variable)at FSharp.Data.Sql.Providers.OdbcProvider.createUpdateCommand(IDBCConnection con、StringBuilder sb、SqlEntity、FSharpList`1 changedColumns) 地址:$Providers.Odbc.FSharp-Data-Sql-Common-ISql

我有以下F#代码

新的错误是:

System.Exception:错误-无法更新未更新的实体 有一个主键。(dbo.variable)at FSharp.Data.Sql.Providers.OdbcProvider.createUpdateCommand(IDBCConnection con、StringBuilder sb、SqlEntity、FSharpList`1 changedColumns)

地址:$Providers.Odbc.FSharp-Data-Sql-Common-ISqlProvider-ProcessUpdates@648-4.调用(SqlEntity) e) 在 Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc
2操作,
IEnumerable
1源代码)位于 FSharp.Data.Sql.Providers.OdbcProvider.FSharp数据Sql公共ISqlProvider进程更新(IDBCConnection con,ConcurrentDictionary
2个实体,事务选项
transactionOptions,FSharpOption
1超时) .$SqlRuntime.DataContext。f@1-69(SqlDataContext) __,IDbConnection con,Unit unitVar0),位于FSharp.Data.Sql.Runtime.SqlDataContext.FSharp-Data-Sql-Common-ISqlDataContext-SubmitPendingChanges()处


有没有关于如何处理这个问题的想法?

我发现了一个棘手/肮脏的方法,我将其归类为一个解决办法,而不是真正的解决方案,但它在我的情况下起作用;所以我将使用它,除非/直到其他人提出结论性的建议

要使类型提供程序正常工作,我需要执行常规工作流中没有的两项操作:

  • 需要在禁用事务的情况下检索数据上下文
  • 在对DBF执行更改操作之前,我创建了一个主 使用较低级别的SQL语句输入该DBF
  • 这是工作代码

    [<Literal>]
    let private schemaConn = @"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=C:\Citect\User\NPM;READONLY=FALSE" 
    type private schema = SqlDataProvider<Common.DatabaseProviderTypes.ODBC, schemaConn>
    let private connStringFormat = Printf.StringFormat<string->string>(@"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=%s;READONLY=FALSE")
    
    type internal Project = {
        name : string
        path : string
        dcx : schema.dataContext
    }
    
    [<Literal>]
    let private cUserPath = @"C:\Citect\User"
    
    let private findPath projectName = 
        Directory.GetDirectories(cUserPath, projectName, SearchOption.AllDirectories)
        |> Array.find (fun d -> d.Contains("web") |> not)
    
    let private createPK (cn : IDbConnection) = 
        let cm = cn.CreateCommand()
        cm.CommandText <- "ALTER TABLE Variable ADD PRIMARY KEY (Name)"
        try
            cn.Open()
            cm.ExecuteNonQuery() |> ignore
        finally cn.Close()
    
    let internal connect projectName =
        let path' = findPath projectName
        let connString = sprintf connStringFormat path'
        let transOptions = { Timeout = TimeSpan.FromSeconds(3.0); IsolationLevel = Transactions.IsolationLevel.DontCreateTransaction }
        let dcx' = schema.GetDataContext(connectionString = connString, transactionOptions = transOptions)
        dcx'.CreateConnection() |> createPK
        { name = projectName; path = path'; dcx = dcx' }
    
    let internal updVariable (project : Project) variable = 
        let dcx = project.dcx
        let q = query {
            for v in dcx.Dbo.Variable do
                where (v.Addr = "%MW217.0")
                select v
                exactlyOne
        }
        q.Addr <- "QQQ"
        dcx.SubmitUpdates()
    
    let internal prj = connect "NPMUG_SCC35"
    updVariable prj ()
    
    []
    让私有schemacon=@“Driver={Microsoft数据库驱动程序(*.dbf)};DriverID=277;Dbq=C:\Citect\User\NPM;READONLY=FALSE”
    类型private schema=SqlDataProvider
    让private connStringFormat=Printf.StringFormatstring>(@“驱动程序={Microsoft数据库驱动程序(*.dbf)};DriverID=277;Dbq=%s;只读=FALSE”)
    类型内部项目={
    名称:string
    路径:字符串
    dcx:schema.dataContext
    }
    []
    让私有cUserPath=@“C:\Citect\User”
    让私有findPath项目名=
    目录.getDirectory(cUserPath、projectName、SearchOption.AllDirectories)
    |>Array.find(fund d->d.Contains(“web”)|>not)
    让私有createPK(cn:IDbConnection)=
    设cm=cn.CreateCommand()
    命令文本忽略
    最后cn.Close()
    让内部连接projectName=
    让路径“=findPath projectName
    让connString=sprintf connStringFormat路径'
    let transOptions={Timeout=TimeSpan.FromSeconds(3.0);IsolationLevel=Transactions.IsolationLevel.DontCreateTransaction}
    让dcx'=schema.GetDataContext(connectionString=connString,transactionOptions=transOptions)
    dcx'.CreateConnection()|>createPK
    {name=projectName;path=path';dcx=dcx'}
    让内部UPD变量(项目:项目)变量=
    设dcx=project.dcx
    设q=query{
    对于dcx.Dbo.do变量中的v
    其中(v.Addr=“%MW217.0”)
    选择v
    精确的
    }
    q、 地址
    
    let dcx = schema.GetDataContext( { Timeout = TimeSpan.MaxValue; IsolationLevel = Transactions.IsolationLevel.DontCreateTransaction } : FSharp.Data.Sql.Transactions.TransactionOptions)
    
    [<Literal>]
    let private schemaConn = @"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=C:\Citect\User\NPM;READONLY=FALSE" 
    type private schema = SqlDataProvider<Common.DatabaseProviderTypes.ODBC, schemaConn>
    let private connStringFormat = Printf.StringFormat<string->string>(@"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=%s;READONLY=FALSE")
    
    type internal Project = {
        name : string
        path : string
        dcx : schema.dataContext
    }
    
    [<Literal>]
    let private cUserPath = @"C:\Citect\User"
    
    let private findPath projectName = 
        Directory.GetDirectories(cUserPath, projectName, SearchOption.AllDirectories)
        |> Array.find (fun d -> d.Contains("web") |> not)
    
    let private createPK (cn : IDbConnection) = 
        let cm = cn.CreateCommand()
        cm.CommandText <- "ALTER TABLE Variable ADD PRIMARY KEY (Name)"
        try
            cn.Open()
            cm.ExecuteNonQuery() |> ignore
        finally cn.Close()
    
    let internal connect projectName =
        let path' = findPath projectName
        let connString = sprintf connStringFormat path'
        let transOptions = { Timeout = TimeSpan.FromSeconds(3.0); IsolationLevel = Transactions.IsolationLevel.DontCreateTransaction }
        let dcx' = schema.GetDataContext(connectionString = connString, transactionOptions = transOptions)
        dcx'.CreateConnection() |> createPK
        { name = projectName; path = path'; dcx = dcx' }
    
    let internal updVariable (project : Project) variable = 
        let dcx = project.dcx
        let q = query {
            for v in dcx.Dbo.Variable do
                where (v.Addr = "%MW217.0")
                select v
                exactlyOne
        }
        q.Addr <- "QQQ"
        dcx.SubmitUpdates()
    
    let internal prj = connect "NPMUG_SCC35"
    updVariable prj ()