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# 代码将无法编译。)
我正在使用 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# 代码将无法编译。)