As shown in https://docs.servicestack.net/autoquery-crud#optimistic-concurrency I would like to define a Create and Update service that inherits from an underlying type as follows:
[Route("/api/app/user-setting", "POST")]
[AutoApply(Behavior.AuditCreate)]
public class CreateUserSetting : UserSetting, ICreateDb<UserSetting>, IReturn<GuidResponse>, IPost
{
}
[Route("/api/app/user-setting/{Id}", "PUT")]
[AutoApply(Behavior.AuditModify)]
public class UpdateUserSetting : UserSetting, IUpdateDb<UserSetting>, IReturn<GuidResponse>, IPut
{
}
[Schema("App")]
[DataContract]
public class UserSetting : MyAuditBase
{
[AutoId]
[DataMember, Required]
[IgnoreOnInsert]
public Guid Id { get; set; }
[DataMember, Required]
public Guid AccountId { get; set; }
[DataMember, Required]
public string KeyName { get; set; } = null!;
[DataMember, Required]
public string KeyValue { get; set; } = null!;
[DataMember]
public string? Description { get; set; }
[DataMember, Required]
[Alias("DataEventRv")]
[IgnoreOnInsert]
public ulong RowVersion { get; set; }
}
The corresponding database table is defined as
CREATE TABLE App.UserSetting (
-- referential
Id UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID(),
IndexId INT IDENTITY(1,1),
-- Lookup data
AccountId UNIQUEIDENTIFIER NOT NULL,
KeyName NVARCHAR(60) NOT NULL,
KeyValue NVARCHAR(240) NOT NULL,
Description NVARCHAR(240) NULL,
DataEventRv ROWVERSION NOT NULL,
DataEventOn DATETIME2 NOT NULL,
DataEventId TINYINT NOT NULL,
DataEventBy UNIQUEIDENTIFIER NOT NULL,
)
The MyAuditBase class handles the autopopulation of the audit fields (DataEventId, DataEventOn and DataEventBy). The Update service is working correctly.
However, when calling the Create service the Rowversion (DataEventRv) is not being ignored on insert, so it causes a database (MSSSQL) exception:
Create Request (POST):
{
"Id": "00000000000000000000000000000000",
"AccountId": "603296de63abec11b596482ae316d296",
"KeyName": "K2",
"KeyValue": "V2",
"Description": "D2",
"RowVersion": 0
}
Error Response:
{
"id": "00000000000000000000000000000000",
"responseStatus": {
"errorCode": "SqlException",
"message": "Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column.",
"stackTrace": null,
"errors": [],
"meta": null
}
}
The output from using PrintSQL, below, shows that a value is being inserted for the RowVersion (DataEventRv):
SQL: INSERT INTO "App"."UserSetting" ("AccountId","KeyName","KeyValue","Description","DataEventRv","DataEventId","DataEventOn","DataEventBy")
OUTPUT INSERTED."Id"
VALUES (@AccountId,@KeyName,@KeyValue,@Description,@DataEventRv,@DataEventId,@DataEventOn,@DataEventBy)
PARAMS: @AccountId=603296de-63ab-ec11-b596-482ae316d296, @KeyName=K2, @KeyValue=V2, @Description=D2, @DataEventRv=0, @DataEventId=1,
@DataEventOn=2022-03-30 03:58:09, @DataEventBy=603296de-63ab-ec11-b596-482ae316d296
Is it possible to have RowVersion ignored on insert, or is it using a special convention that bypasses the ignore attribute?
Running under windows with ServiceStack 6.0.3; C#10; Net6; MSSQL 2019