Oracle EF mapping NUMBER(n, n) data types

In a recent project we built a template based code generator to help us rapidly build out OData ASP.NET Api services over an existing Oracle database using Entity Framework. The first cut used a default mapping of decimal for each Oracle NUMBER(n, n) column found, and we started getting messages like the following:

Member Mapping specified is not valid. The type 'Edm.Decimal[Nullable=False,DefaultValue=,Precision=6,Scale=0]' of member 'Property' in type 'TypeName' is not compatible with 'OracleEFProvider.number[Nullable=False,DefaultValue=,Precision=6,Scale=0]' of member 'Column' in type 'CodeFirstDatabaseSchema.Table'.\r\n(469,12) : error 2019: Member Mapping specified is not valid. 

Clearly just using the basic mapping was not correct!

In the Oracle data provider documentation it describes how the NUMBER(n, 0) data types map to various integer data types:

https://docs.oracle.com/database/121/ODPNT/entityEDMmapping.htm#ODPNT8275

So it was easy to work out how we could use the scale and precision values to correct map the various NUMBER data types. What was pretty interesting to discover, however, is that you can change these mappings through config – the example given in the docs being to take a NUMBER(1, 0) column direct to a bool data type. Useful.

https://docs.oracle.com/database/121/ODPNT/entityDataTypeMapping.htm#ODPNT8300

Angular binding boolean (k)nots!

It seems like a trivial task. In an Angular app change a checkbox that manages the Deleted ‘soft delete’ property to invert and show as an Active property.

So the naive approach is just to try and change the two way model binding to ! the boolean value – something like:

<input name="IsDeleted" type="checkbox" [(ngModel)]="!input.IsDeleted">

Frighteningly this very nearly works! But you will find the behaviour of the model set is not correct, requiring two clicks on the check box – to be fair the docs do say to only set a data-bound property. So what do you do?

To stick with the two way data-binding syntax you could add getter/setter accessors on the component itself:

get isActive() { return !this.input.IsDeleted; } set isActive(newValue: boolean) { this.input.IsDeleted = !newValue; }

then use as the target of the simple two way data-bind expression:

<input name="IsDeleted" type="checkbox" [(ngModel)]="isActive">

Personally I think a more elegant is to use the one way binding to display the inverted value and the event syntax (for the checkbox the change event) to set the inverted value:

<input name="IsDeleted" type="checkbox" [ngModel]="!input.IsDeleted" (change)="input.IsDeleted=!$event.target.checked">

Angular bind ! of Boolean property

It seems like a trivial task. In an Angular app change a checkbox that manages the Deleted ‘soft delete’ property to invert and show as an Active property.

So the naive approach is just to try and change the two way model binding to ! the boolean value – something like:

<input name="IsDeleted" type="checkbox" [(ngModel)]="!input.IsDeleted">
<input name="IsDeleted" type="checkbox" class="form-control" [(ngModel)]="!input.IsDeleted" [disabled]="!canWrite">

Frighteningly this very nearly works! But you will find the behaviour of the model set is not correct, requiring two clicks on the check box – to be fair the docs do say to only set a data-bound property. So what do you do?

To stick with the two way data-binding syntax you could add getter/setter accessors on the component itself:

get isActive() { return !this.input.IsDeleted; } set isActive(newValue: boolean) { this.input.IsDeleted = !newValue; }

then use these as the target of the two way data-bind expression:

<input name="IsDeleted" type="checkbox" [(ngModel)]="isActive">

Personally I think a more elegant is to use the one way binding to display the inverted value and the event syntax (for the checkbox the change event) the set the inverted value:

<input name="IsDeleted" type="checkbox" class="form-control" [ngModel]="!input.IsDeleted" (change)="input.IsDeleted=!$event.target.checked" [disabled]="!canWrite">
<input name="IsDeleted" type="checkbox" [ngModel]="!input.IsDeleted" (change)="input.IsDeleted=!$event.target.checked">