Autocrud delete audit created but record not affected

ServiceStack 8.2.2 Autoquery crud delete is not working for me as expected.

These are my classes:

public class Company : AuditBase
{
    [AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }

    [Reference]
    public CompanyDetails CompanyDetails { get; set; }

    [Reference]
    public List<Employee> Employees { get; set; }

    [Reference]
    public List<ApplicationUserCompany> ApplicationUserCompanies { get; set; } 

}

public class CompanyDetails : AuditBase
{
    [AutoIncrement]
    public int Id { get; set; }
    [References(typeof(Company))]
    public int CompanyId { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
}

[ValidateIsAdmin]
[AutoApply(Behavior.AuditCreate)]
public class CreateCompany : ICreateDb<Company>, IReturn<IdResponse>
{
    public string Name { get; set; }
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    [Input(Type = Input.Types.Tag)]
    public List<string> ApplicationUserIds { get; set; }
}

[ValidateIsAdmin]
[AutoApply(Behavior.AuditModify)]
public class UpdateCompany : IUpdateDb<Company>, IReturn<Company>
{
    public int Id { get; set; }
    public string Name { get; set; }
    public CompanyDetails CompanyDetails { get; set; }
}

[ValidateIsAdmin]
[AutoApply(Behavior.AuditDelete)]
public class DeleteCompany : IDeleteDb<Company>, IReturnVoid
{
    public int Id { get; set; }
}

[ValidateIsAdmin]
[AutoApply(Behavior.AuditCreate)]
public class CreateCompanyDetails : ICreateDb<CompanyDetails>, IReturn<IdResponse>
{
    public string Street1 { get; set; }
    public string Street2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Country { get; set; }
    [References(typeof(Company))]
    [ValidateNotNull]
    public int CompanyId { get; set; }
}

and my setup

    public void Configure(IWebHostBuilder builder) => builder
        .ConfigureServices(services =>
        {
            // Enable Audit History
            services.AddSingleton<ICrudEvents>(c =>
                new OrmLiteCrudEvents(c.GetRequiredService<IDbConnectionFactory>()));

            services.AddPlugin(new AutoQueryDataFeature());

            services.AddPlugin(new AutoQueryFeature
            {
                MaxLimit = 1000,
                //IncludeTotal = true,
                
            });
        })
        .ConfigureAppHost(appHost =>
        {
            appHost.Resolve<ICrudEvents>().InitSchema();
        });

I can use CreateCompany to create a company via API/Locode fine but when I hit DeleteCompany nothing happens apart from a delete audit event being created. The deleted date or deleted by are not set. I am not exactly sure after reading docs if softdelete should be default. I assumed softdelete only happens if its specified and hard delete otherwise.

No errors are returned and I am able to delete directly from database without any issue. Audit events created correctly but nothing updated on main record to indicate it has been deleted. I just tested also with a simple class with no relationships and same behaviour.

Am I missing something?

If you want soft delete use the SoftDelete behavior:

[AutoApply(Behavior.AuditSoftDelete)]

Which changes the behavior to an Update and should populate the DeletedDate & DeletedBy fields.

If you want to delete the record, don’t use apply any Behavior attribute (i.e. remove the attribute).

Its not working then. I don’t have the attribute and the record it not deleted but the audit event is created.

I am using ServiceStack.OrmLite.PostgreSQL 8.2.2. No errors, it returns 200 but doesn’t delete the record.

If you put a repro on GitHub I’ll take a look at it tomorrow.

Thanks Mythz.

I am using PostgreSQL 14. If you open up locode and add a company then try to delete it an audit will get created but the record does not get deleted.

user is seeded in Configure.Auth.cs.

I said you needed to switch to either AuditSoftDelete to populate the Deleted By fields or remove the attribute to get it to delete, but the repro still uses [AutoApply(Behavior.AuditDelete)]?

Remove the attribute to get it to delete:

[ValidateIsAdmin]
// [AutoApply(Behavior.AuditDelete)]
public class DeleteCompany : IDeleteDb<Company>, IReturnVoid
{
    public int Id { get; set; }
}

Thanks for looking at it Mythz.

Sorry, I am still a bit confused. The docs say:

but with that property there like so (as in the standalone repo)

    [ValidateIsAdmin]
    [AutoApply(Behavior.AuditDelete)]
    public class DeleteCompany : IDeleteDb<Company>, IReturnVoid
    {
        public int Id { get; set; }
    }

Then when deleting the company nothing happens apart from the crud audit event being created. The record is not deleted.

Removing attribute makes it fully delete and the crud event gets created but why does adding this attribute prevent the record from being deleted? And why does the audit still get created when the apply audit attribute is removed?

If you want to a normal delete remove all audit attributes, if you want a soft delete use the AuditSoftDelete attribute instead:

[AutoApply(Behavior.AuditSoftDelete)]

I get that is what is happening but what is this attribute meant to do?

[AutoApply(Behavior.AuditDelete)]

And why is the audit getting created if the is audit attribute is removed?

I appreciate your patience with me on this.

It just populates DeletedDate and DeletedBy fields on the underlying data model, please use Behavior.AuditSoftDelete instead if you want soft delete behavior for your AuditBase classes.

You’re getting Audit events because you have an ICrudEvents provider registered, you can control which records you want audit events for by using a EventFilter and returning null for the requests you don’t want audit entries for.

ahhh ok, that was my misunderstanding. I thought it was enabling the audit data.

I think my confusion came from the locode docs saying

The appropriate [AutoApply] behavior needs to be added on all the CRUD APIs for the data models we want Audit History tracking enabled on, e.g:

Use Behavior.AuditDelete instead if you prefer your delete operations resulted in permanent hard deletes

This makes it sound like Behavior.AuditDelete will enable hard deletes and is needed for delete audits.

But going to the AutoQuery CRUD docs it does say that it just populates the meta data.

I think I understand it all now, thanks for the help and sorry to be a pain :slight_smile: