F# SqlProvider:System.Exception:错误 - 您无法更新没有主键的实体。 (public.users)

F# SqlProvider: System.Exception: Error - you cannot update an entity that does not have a primary key. (public.users)

我正在使用 SQLProvider 类型提供程序项目:https://fsprojects.github.io/SQLProvider/

作为 documentation states on CRUD 的用法,我尝试像这样更新一行:

   let UpdateGpsLocation(gpsLocationDetails: UpdateGpsLocation) =
        let ctx = SQL.GetDataContext()

        let maybeFoundUser =
            query {
                for user in ctx.Public.Users do
                    where(user.UserId = gpsLocationDetails.UserId)
                    select(Some user)
                    exactlyOneOrDefault
            }

        match maybeFoundUser with
        | Some user ->
            user.GpsLatitude <- Some gpsLocationDetails.Latitude
            user.GpsLongitude <- Some gpsLocationDetails.Longitude
            ctx.SubmitUpdates()
        | None -> failwithf "User %i not found" gpsLocationDetails.UserId

但是它失败了:

  System.Exception: Error - you cannot update an entity that does not have a primary key. (public.users)
     at FSharp.Data.Sql.Providers.PostgresqlProvider.createUpdateCommand(IDbConnection con, StringBuilder sb, SqlEntity entity, FSharpList`1 changedColumns)
     at <StartupCode$FSharp-Data-SqlProvider>.$Providers.Postgresql.FSharp-Data-Sql-Common-ISqlProvider-ProcessUpdates@1205-8.Invoke(SqlEntity e)
     at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source) in D:\a\_work\s\src\fsharp\FSharp.Core\seq.fs:line 497
     at FSharp.Data.Sql.Providers.PostgresqlProvider.FSharp-Data-Sql-Common-ISqlProvider-ProcessUpdates(IDbConnection con, ConcurrentDictionary`2 entities, TransactionOptions transactionOptions, FSharpOption`1 timeout)
     at <StartupCode$FSharp-Data-SqlProvider>.$SqlRuntime.DataContext.FSharp-Data-Sql-Common-ISqlDataContext-SubmitPendingChanges@110.Invoke(Unit unitVar0)
     at FSharp.Data.Sql.Runtime.SqlDataContext.FSharp-Data-Sql-Common-ISqlDataContext-SubmitPendingChanges()
     at BackendDataLayer.Access.UpdateGpsLocation(UpdateGpsLocation gpsLocationDetails) in C:\Users\knocte\Documents\Code\RunIntoMeMASTER\src\BackendDataLayer\Access.fs:line 34

但是table有一个主键!特别是,它使用了 PostgreSQL 的 SERIAL 特性,这样:

CREATE TABLE users (
    user_id SERIAL PRIMARY KEY
    , gps_latitude FLOAT8
    , gps_longitude FLOAT8
);

这是 SqlProvider 项目中的错误吗?或者可能只是在它的 PostgreSQL 组件中?

我能够重现这个问题,这里使用 user_id 作为列名似乎有问题。

这只是一种解决方法,但将列名称更改为 "UserId"(包括 double-quotes!)解决了我的问题。

查看新架构:

CREATE TABLE "Users" (
    "UserId" SERIAL PRIMARY KEY
    , "GpsLatitude" FLOAT8
    , "GpsLongitude" FLOAT8
);

(如果您不使用 double-quotes,它会将 UserId 转换为 Userid,您的 F# 代码将无法编译。)