ServiceStack / Issues

Issue Tracker for the commercial versions of ServiceStack
11 stars 6 forks source link

AutoQueryFeature/locode changes break OrmLiteConfig.InsertFilter/UpdateFilter #807

Closed jhf closed 2 weeks ago

jhf commented 2 weeks ago

Describe the issue

I have used the following IAudit setup from https://docs.servicestack.net/ormlite/filters

public interface IAudit 
{
    DateTime CreatedDate { get; set; }
    DateTime ModifiedDate { get; set; }
    string ModifiedBy { get; set; }
}

OrmLiteConfig.InsertFilter = (dbCmd, row) => {
    if (row is IAudit auditRow)
        auditRow.CreatedDate = auditRow.ModifiedDate = DateTime.UtcNow;
};

OrmLiteConfig.UpdateFilter = (dbCmd, row) => {
    if (row is IAudit auditRow)
        auditRow.ModifiedDate = DateTime.UtcNow;
};

But it does not work with /locode using AutoQuery generated types. Upon inspection I found that the row is a DictionaryRow, ref https://docs.servicestack.net/ormlite/dictionary-apis thus my new implementation is

        OrmLiteConfig.InsertFilter = (dbCmd, row) =>
        {
            switch (row)
            {
                case IAudit auditRow:
                    auditRow.CreatedAt = auditRow.UpdatedAt = DateTimeOffset.UtcNow;
                    break;
                case DictionaryRow dictRow when dictRow.Type.HasInterface(typeof(IAudit)):
                    dictRow.Fields[nameof(IAudit.CreatedAt)] = dictRow.Fields[nameof(IAudit.UpdatedAt)] = DateTimeOffset.UtcNow;
                    break;
            }
        };

        OrmLiteConfig.UpdateFilter = (dbCmd, row) =>
        {
            switch (row)
            {
                case IAudit auditRow:
                    auditRow.UpdatedAt = DateTimeOffset.UtcNow;
                    break;
                case DictionaryRow dictRow when dictRow.Type.HasInterface(typeof(IAudit)):
                    dictRow.Fields[nameof(IAudit.UpdatedAt)] = DateTimeOffset.UtcNow;
                    break;
            }
        };

This implementation works, and I consider this a breaking change, I think the old API should have continued to work, and there should maybe be another callback, or a typed callback, to work on the DictionaryRow.

Reproduction

Setup a sample project with IAudit as recommended, configure /locode with AutoQuery, using a PostgreSQL Database, go to /locode and make a new entity, and step through the insert filter with the debugger.

Expected behavior

I expected the existing API to continue working as documented, so the it doesn't matter if changes are done with locode, AutoQuery or code directly, it's all the same behaviour.

System Info

dotnet 8.0.108
ServiceStack 8.4.0
ServiceStack.OrmLite.PostgreSQL 8.4.0

Additional context

No response

Validations

mythz commented 2 weeks ago

The IAudit is an example of how you can filters with your own code which only works for typed POCOs not dynamic data structures as documented.

The filters are accessing internals of how locode works, we can't guarantee data structures locode uses wont change to support features it needs.

jhf commented 2 weeks ago

Ok, maybe you could update the documentation then.

mythz commented 2 weeks ago

We don't have any docs about using filters with Locode nor would we recommend using them to modifying internal data structures.

Is there a reason why you're not using AutoPopulate to populate AutoQuery audit properties?