RowVersion causing NullReferenceException when calling Save on new record

I would like to use the Save option so I can automatically save any references, but I’m getting a NullReferenceException and narrowed it down to the ulong RowVersion property. When doing an Insert on that same Dto, it works fine. Shouldn’t we be able to use the Save with RowVersion for a first time insert?

There is no RowVersion on insert, can you post the StackTrace.

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=ServiceStack.OrmLite
  StackTrace:
   at ServiceStack.OrmLite.OrmLiteExecFilter.<>c__DisplayClass6_0`1.<Exec>b__0(Task`1 t) in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteExecFilter.cs:line 125
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.<>c.<.cctor>b__274_0(Object obj)
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at ServiceStack.OrmLite.OrmLiteWriteApiAsync.<SaveAsync>d__36`1.MoveNext() in C:\BuildAgent\work\27e4cc16641be8c0\src\ServiceStack.OrmLite\OrmLiteWriteApiAsync.cs:line 340
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Platform.ServiceInterface.EntityService.<Post>d__0.MoveNext() in C:\Users\****\Documents\***\***\Platform\Platform.ServiceInterface\EntityService.cs:line 21

Just to clarify, when doing a Save, it bombs. When doing an Insert, it works.

Save & SaveAsync is passing in all supported RDBMS’s

I’ll need a stand-alone repro.

Very possibly implementation specific. I’m sure I have used Save before in combination with RowVersion without a problem. In this case, it’s a multi tenant app using a global request filter to change the connection at run time, but I doubt that has anything to do with it. I’ll try and recreate this in a new app.

Definitely something wrong with Save and RowVersion on PostgreSQL 12.

Started a brand new project with

x new selfhost Selfhost1

Then

mix postgres

Added the following code

TestModel.cs

using ServiceStack;
using ServiceStack.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Text;

namespace SelfHost1.ServiceModel
{
    public class TestModel
    {
        [AutoId]
        public Guid Id { get; set; }
        public string Name { get; set; }
        public ulong RowVersion { get; set; }
    }

    [Route("/test", "POST")]
    public class CreateTestModel
    {
        public string Name { get; set; }
    }

    public class CreateTestModelResponse
    {
        public Guid Id { get; set; }
    }
}

MyServices.cs

namespace SelfHost1.ServiceInterface
{
    public class MyServices : Service
    {
        public object Any(Hello request)
        {
            return new HelloResponse { Result = $"Hello, {request.Name}!" };
        }

        public object Any(CreateTestModel request)
        {
            var model = request.ConvertTo<TestModel>();
            Db.Save(model);
            return new CreateTestModelResponse { Id = model.Id };
        }
    }
}

Same problem. I get a NullReferenceException at Db.Save(model). When I remove the RowVersion property, no error.

Using 5.8.1 for everything.

thx for the repro, should be resolved from this commit that’s now available from the latest v5.8.1 on MyGet.

Thanks, that worked. However, we now have a problem when updating that same record, resulting in a ServiceStack.Data.OptimisticConcurrencyException.

Repro:

TestModel.cs

using ServiceStack;
using ServiceStack.DataAnnotations;
using System;
using System.Collections.Generic;
using System.Text;

namespace SelfHost1.ServiceModel
{
    public class TestModel
    {
        [AutoId]
        public Guid Id { get; set; }
        public string Name { get; set; }
        public ulong RowVersion { get; set; }
    }

    [Route("/test", "POST")]
    public class CreateTestModel
    {
        public string Name { get; set; }
    }

    [Route("/test/{id}", "PATCH")]
    public class UpdateTestModel : IReturn<UpdateTestModelResponse>
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

    public class CreateTestModelResponse
    {
        public Guid Id { get; set; }
    }

    public class UpdateTestModelResponse
    {
        public int Count { get; set; }
    }
}

MyService.cs

using System;
using ServiceStack;
using SelfHost1.ServiceModel;
using ServiceStack.OrmLite;

namespace SelfHost1.ServiceInterface
{
    public class MyServices : Service
    {
        public object Any(Hello request)
        {
            return new HelloResponse { Result = $"Hello, {request.Name}!" };
        }

        public object Post(CreateTestModel request)
        {
            var model = request.ConvertTo<TestModel>();
            Db.Save(model, references:true);
            return new CreateTestModelResponse { Id = model.Id };
        }

        public object Patch(UpdateTestModel request)
        {
            var model = request.ConvertTo<TestModel>();
            return Db.Save(model, references: true);
        }
    }
}

Can you provide the actual client code to run to produce the repro, I can’t see a valid update example here? Every update needs to include the latest RowVersion. What Service are you trying to call, that’s failing?

Note you shouldn’t need to use a Service to provide a repro, it’s easier if you just create a unit test with the DTOs that your Service populates and use it with OrmLite directly, which would also make it clear what you’re trying to do and what doesn’t work.

I’m calling the PATCH method through Swagger with the Id of the existing record and a value for Name.

So I’m supposed to also know and pass in the existing RowVersion with each update? I thought OrmLite took care of that.

That’s how it’s going to know if the update you’re trying to make hasn’t changed since you’ve accessed it. How else is it supposed to know if you’ve got stale data? Doesn’t sound like you want to use optimistic concurrency here then.

Your implementation could do a read, populate the record and save it but that would defeat the purpose in not knowing if the data has changed before you’ve updated it.

Ok, I just re read the docs on that. You’re right. Sorry for the misunderstanding.

1 Like

So I’m wondering, would there be a way to tell OrmLite to optionally ignore this? For example, when testing through Swagger, it would make sense to just ignore it since it’s completely stateless. But through a real UI when the user is updating critical information and have state attached to it, you could have an opportunity to first load the record (along with the RowVersion) and then later update it, checking for concurrency.

From docs:

Optimistic concurrency is only verified on API’s that update or delete an entire entity, i.e. it’s not enforced in partial updates.

So you can use partial update APIs like UpdateOnly, without specifying the RowVersion.

Doesn’t appear the SaveAsync version of this is working.

Crap async version uses a different code-path that also needs this fix applied, added in this commit.

This change is available from the latest v5.8.1 that’s now on MyGet.

Did something break with 5.8.1? Can no longer run the service. It compiles, but bombs out at:

app.UseServiceStack(new AppHost());

Application startup exception: System.TypeLoadException: Could not load type ‘System.Web.IHttpHandler’ from assembly ‘ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=null’.

I’ve moved the .NET Core portability types out of ASP .NET’s System.Web namespace (into ServiceStack.Host).

You’ll need a clean re-compile your existing binaries, i.e. any Assembly trying to load System.Web.IHttpHandler is old. So in addition to clearing your NuGet cache:

$ nuget locals all -clear

Since it looks your ServiceStack.dll is old, you should try removing the bin and obj folders as well:

$ rd /q /s bin obj

Please let me know if clearing your caches & binary folders resolves it?