Partial Update of Child Object on Parent Table

I have an object (MyDerivedType) used to support an AutoQuery API. This class is a composite of a Base class (which contains about 100 fields, including the ID) and 3 additional fields. At the end of the day, the MyDerivedType table needs to have all properties created as separate fields so that AutoQuery can correctly allow the user access only to what they need. The row in the MyDerivedTypetable is created when we received the information in the Base class (use db.InsertAsync and a copy constructor on MyDerivedTypewhich takes Base as input) and the other 4 fields are updated at various with UpdateOnlyAsync and all is well in the world.

From time to time, we will need to update the Base information (all of it) for a particular MyDerivedType, without overwriting the values we had in the table already for the 3 additional fields. Here is where I run into a problem. If I use the copy constructor on the MyDerivedType class and UpdateAsync, it tramples the values in those other 3 fields. Writing code which actually spells out the fields in Base and using UpdateAsync with only those specified fields would work technically, but is not desired as we don’t want to keep a second separate list of all properties in sync all the time (aside from the fact that writing that code would be insanely boring :slight_smile: ). Having an instance of the Base class as a property inside of MyDerivedType so 1:1 property assignment can be done solves the enumeration challenge, but we then lose the functionality we need from AutoQuery since those 100 properties would get stored as a blob and therefore not independently query-able.

Whose got a clever solution for me?

[Alias("MyDerivedType")]
public class MyDerivedType : Base
{
    public MyDerivedType(Base input) { //copy constructor code here}

    public virtual int Status { get; set; }
    public virtual DateTime TimeStamp { get; set; }
    public virtual int FundingResult { get; set; }
}

[Alias("Base")]
public class Base
{
    public virtual Guid Id { get; set; }
    //99 more properties
}

//this overwrites the other 3 fields as we would expect, but not as we want
Base myBase; 
await db.UpdateAsync<MyDerivedType>(myBase, p => p.Id == myBase.Id).ConfigureAwait(false);

Have a look at the UpdateOnly APIs with some Live Examples you can play around with on Gistlyn which let you explicitly control which fields should be updated.

There’s also UpdateNonDefaults if your data allows for it where OrmLite will only update fields with non-default values.

Personally I don’t like copy constructors, I’d rather use extension methods to keep the data models clean and decoupled from other types.

I appreciate the response but it seems you are missing the issue. I’ve seen the UpdateOnly examples. Unless I missed something, as I explained, I didn’t see any way to use the partial update with explicitly enumerating the fields which as I explained is problematic. Am I missing something?

Then I don’t think I understand, as you’re aware you can’t use a complex type property as that will be blobbed, but you could have it as a 1:1 reference property where the extra fields are maintained in a completely separate table, at which point you don’t want to inherit Base just have contained in a separate public property (that you’ll then want to rename to a different table/class than Base). Having it as a reference property will affect AutoQuery where you’ll need to use a JOIN and prefix each property with the table name to be able to query the joined table.

For the cleanest AutoQuery API you’ll want to keep your table POCO flat, either by having explicit properties or inheriting Base.

You could then use AutoMapping to copy matching properties from 1 model to another. The UpdateOnly API includes a way to specify which field names you want updated, e.g:

var fieldNames = new List<string>(); //specify which field names you want updated

model.PopulateWith(input);

db.UpdateOnly(model, 
    onlyFields: p => fieldNames.ToArray() });

From your description it looks like db.UpdateOnly() above is the OrmLite API you want to use, or you could use the full db.Update() API and if your issue is that existing properties are being overwritten, you can hold them and recopy them after using AutoMapping to populate it, e;g:

var holdStatus = model.Status;
model.PopulateWith(input);
model.Status = holdStatus;

If you need to the C#/.NET Reflection APIs are what you’ll use to enumerate properties on a model if you need to, or if you need more fine-grained control than that then just copy of the properties you need to explicitly, how properties are mapped are just C# logic at the end of the day.

If none of the above helps, I’m not sure what else you’re looking for - the part that’s not OrmLite is just using vanilla C# to do what you need. OrmLite data models are just plain POCOs that are decoupled from OrmLite, so you can happily use the C# you’re comfortable with to populate the models.

Explicitly naming the fields in UpdateOnly is problematic since there are 100 fields that change somewhat frequently and we don’t want to maintain the field names in two different locations (hence the inheritance). Does that clarify the constraint? Something like auto mapper would be fine, except how does that help UpdateOnly? Wouldn’t UpdateOnly still require explicit enumeration of each field to avoid trampling the data in the other 3 fields? We don’t care if we use UpdateOnly or any other API - I was just using UpdateOnly to show the problem.

You can get the field names of the base class via reflection:

typeof(Base).GetProperties().Select(p => p.Name).ToArray();

And pass this list of property names to UpdateOnly.

Thanks mythz and explicit - I understand that solution now. Mythz also mentioned used UpdateNonDefaults earlier - does that update all fields except where the instance has default values (which would also solve this) or all fields except where the table row has default values (which would trample the values in those 3 fields)?

It updates fields with non-default values, so if the model was only populated with Base properties only they would be updated.

Great - that looks like an even better solution then using reflection! I tried to follow your suggestion and change the copy constructor to use .PopulateWith method but by compiler can’t find it. Documentation online says I need ServiceStack.Common referenced/using which I have but still no luck. Do I need to decorate my class with something so that PopulateWith will recognize it and exist as an extension method? Using latest SS btw.

PopulateWith is an extension method in the ServiceStack.Text assembly in the ServiceStack namespace. OrmLite depends on ServiceStack.Text so you should already have the dependency, you just need the using ServiceStack; namespace if you haven’t already.

Perfect - everything working now - thanks so much!

For others:

Base myBase; 
await db.UpdateNonDefaultsAsync(new MyDerivedType{ }.PopulateWith(myBase), p => p.Id == myBase.Id).ConfigureAwait(false);