-
Notifications
You must be signed in to change notification settings - Fork 108
Update Expressions
When specifying what action should be done in the update clause, the library expects an expression that initialises a new instance of the model object, initialising the properties that are to be updated with the new values. This makes it possible to evaluate this, and convert it to a clean SQL statement, that may use existing values in the table, rather than being restricted to just assigning constant values.
There are two overrides to the .WhenMatched() method, receiving one and two parameters respectively. The first parameter contains the entity that's currently stored in the database, and which is going to be updated. The second parameter (if passed) contains the object that we attempted to insert.
These allow us to handle some useful scenarios. For example, if you want to track views on a document per day, you can either insert a new entry with a value of Views column to 1 (for the initial view), or increase the value by one. You'd use this expression:
.WhenMatched(v => new DocumentView { Views = v.Views + 1 })If instead you want to populate a list of possible DocumentStatus types in the database, ensuring that the latest description is updated, if the entry already existed, you can do this:
.WhenMatched((ds, dsi) => new DocumentStatus { Description = dsi.Description })You could of course just pass in the value you tried to insert, but there are two benefits to using the above approach:
- This approach will reuse the query parameter that was used in the Insert clause, instead of having a second parameter with the same value
- If you're trying to insert multiple values at the same time, this is the only way to achieve this, if you have different descriptions per status (which you probably have)
Besides just assigning values, you can perform basic operations on the values you're trying to assign. There are several kinds of operation currently supported. Note that some operations will only be supported on values that are not part of the database objects, and will have to be passed as constants, as they won't be translated to native sql:
- Addition (
v.Status + 1) - Subtraction
- Multiplication
- Division
- Modulo
- Method calls (
requestUrl.Trim()) - Static methods and properties (
DateTime.Now,String.Join())
As the library has to parse the expression tree, some expressions haven't been explicitly handled yet. In such a case, the library will throw a UnsupportedExpressionException:
This type of expression is not currently supported: {expression extract}. Simplify the expression, or try a different one. See https://go.flexlabs.org/upsert.expressions for more details
There are two solutions to this at the moment:
- Report the exception in the issue tracker here, and we can add support for a new, previously unhandled type of operation
- For constant values (not dependent on values in the database), the expression can be compiled and run on the fly. This option is disabled by default, since it will inherently be slower than evaluating the expression. In simple scenarios this will most likely not be an issue, but in high load scenarios, it should be avoided.
To enable the expression compiler, run
.WithFallbackExpressionCompiler()on the upsert command, before calling.Run().