Sir Thomas - 377 - Nov 20, 2014

Possible bug in Db.UpdateOnly(model, ev) ?

I am using version 24, and did a quick test with 33 to confirm, and there appears to be a bug in the Db.UpdateOnly when using an ExpressionVisitor to specify the UpdateFields, and one of those fields is a TimeSpan.   The console prints an error referring to “ToUpdateRowStatement”, saying that the timespan property does not implement IConvertible.

Interestingly, the same model works fine for other other statements, selects, etc.

snippet…

foreach (Thing q in thingList)
{
var ev = OrmLiteConfig.DialectProvider.SqlExpression<Thing>();
ev.Where(t => t.Id == q.Id);
ev.UpdateFields = q.GetChangedFields();
Db.UpdateOnly<Thing>(q, ev);
}

Hi Thomas, I’ve found the same error when I added TimeSpan to one of the test models, this error was resolved with this commit:
https://github.com/ServiceStack/ServiceStack.OrmLite/commit/fae59b4a246666ce34aa125ff8f439b15d982d31

This change has now been deployed to MyGet: https://github.com/ServiceStack/ServiceStack/wiki/MyGet

Sir Thomas:

Thanks.
The only other quirk in that code snippet is that with an EV specifying UpdateFields, I have to force a Where clause to match Ids.  Since the command is Db.Update and a model is passed (or list of models), I would have assumed that each row would have matched Id by default.  Feels like running an Update statement without a per-row where clause on a list is not typical (ie: update column X set = Y for all rows) and could easily break unique constraints.

Using the db.Update(row) API uses the Id primary key by default, but if you supply new Sql Expression you’re responsible for the query that gets created, just like a normal SQL Update statement. 

Sir Thomas:

I understand that part - except there is no field list as string array option.  Typical intent of UpdateOnly as compared to Update is not to change the where clause, only the fields that change.

I’m not following, UpdateOnly is an API to be able to update only a partial set of fields with the specified where clause. There’s no implicit where cause since any partial fields can be used, (i.e it’s not a complete entity and doesn’t have to include the PK). The API only accepts a single entity, if you want to update multiple entities call the API each time.

Sir Thomas:

I guess it is debatable about the implicit where clause.  If you want we can move the question offline and I can go into more details - but it’s not a big deal, easy to inject the Id.

Yes, the api is called in a loop for multiple entities.