I'm using the SQLProvider type-provider project: https://fsprojects.github.io/SQLProvider/
As the documentation states on CRUD usage, I'm trying to update a row like this:
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
But it is failing with this:
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\1\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
But the table has a primary key! In particular, it's using the SERIAL
feature of PostgreSQL, this way:
CREATE TABLE users (
user_id SERIAL PRIMARY KEY
, gps_latitude FLOAT8
, gps_longitude FLOAT8
);
Is this a bug in SqlProvider project? Or maybe just in its PostgreSQL component?
I was able to reproduce this problem, there seems to be an issue with using user_id
as the column name here.
This is just a workaround but changing the column name to "UserId"
(double-quotes included!) fixed the issue for me.
See the new schema:
CREATE TABLE "Users" (
"UserId" SERIAL PRIMARY KEY
, "GpsLatitude" FLOAT8
, "GpsLongitude" FLOAT8
);
(If you don't use the double-quotes, it will convert UserId
into Userid
and your F# code won't compile.)