Skip to main content
Version: 19

Entity

An entity is an instance of a Dataclass, like a record of the table matching the dataclass in its associated datastore. It contains the same attributes as the dataclass as well as the data values and specific properties and functions.

Summary

.attributeName : any    stores the attribute value for the entity
.clone() : 4D.Entity    creates in memory a new entity referencing the same record as the original entity
.diff( entityToCompare : 4D.Entity { ; attributesToCompare : Collection } ) : Collection    compares the contents of two entities and returns their differences
.drop( {mode : Integer} ) : Object    deletes the data contained in the entity from the datastore
.first(): 4D.Entity    returns a reference to the entity in first position of the entity selection which the entity belongs to
.fromObject( filler : Object )    fills an entity with the filler content
.getDataClass() : 4D.DataClass    returns the dataclass of the entity
.getKey( { mode : Integer } ) : Text
.getKey( { mode : Integer } ) : Integer
    returns the primary key value of the entity
.getSelection(): 4D.EntitySelection    returns the entity selection which the entity belongs to
.getStamp() : Integer     returns the current value of the stamp of the entity
.indexOf( { entitySelection : 4D.EntitySelection } ) : Integer    returns the position of the entity in an entity selection
.isNew() : Boolean     returns True if the entity to which it is applied has just been created and has not yet been saved in the datastore
.last() : 4D.Entity    returns a reference to the entity in last position of the entity selection which the entity belongs to
.lock( { mode : Integer } ) : Object    puts a pessimistic lock on the record referenced by the entity
.next() : 4D.Entity    returns a reference to the next entity in the entity selection which the entity belongs to
.previous() : 4D.Entity     returns a reference to the previous entity in the entity selection which the entity belongs to
.reload() : Object    reloads the content of the entity in memory
.save( { mode : Integer } ) : Object    saves the changes made to the entity
.toObject() : Object
.toObject( filterString : Text { ; options : Integer} ) : Object
.toObject( filterCol : Collection { ; options : Integer } ) : Object
    returns an object which has been built from the entity
.touched() : Boolean    tests whether or not an entity attribute has been modified since the entity was loaded into memory or saved
.touchedAttributes() : Collection    returns the names of the attributes that have been modified since the entity was loaded into memory
.unlock() : Object    removes the pessimistic lock on the record matching the entity

.attributeName

History
ReleaseChanges
17Added

.attributeName : any

Description

Any dataclass attribute is available as a property of an entity, which stores the attribute value for the entity.

Dataclass attributes can also be reached using the alternate syntax with [ ].

The attribute value type depends on the attribute kind (relation or storage):

  • If attributeName kind is storage: .attributeName returns a value of the same type as attributeName.
  • If attributeName kind is relatedEntity: .attributeName returns the related entity. Values of the related entity are directly available through cascading properties, for example "myEntity.employer.employees[0].lastname".
  • If attributeName kind is relatedEntities: .attributeName returns a new entity selection of related entities. Duplications are removed (an unordered entity selection is returned).

Example

 var $myEntity : cs.EmployeeEntity
$myEntity:=ds.Employee.new() //Create a new entity
$myEntity.name:="Dupont" // assign 'Dupont' to the 'name' attribute
$myEntity.firstname:="John" //assign 'John' to the 'firstname' attribute
$myEntity.save() //save the entity

.clone()

History
ReleaseChanges
17Added

.clone() : 4D.Entity

ParameterTypeDescription
Result4D.Entity<-New entity referencing the record

Description

The .clone() function creates in memory a new entity referencing the same record as the original entity.

This function allows you to update entities separately. Note however that, for performance reasons, the new entity shares the same reference of object attributes as the cloned entity.

Keep in mind that any modifications done to entities will be saved in the referenced record only when the .save() function is executed.

This function can only be used with entities already saved in the database. It cannot be called on a newly created entity (for which .isNew() returns True).

Example

 var $emp; $empCloned : cs.EmployeeEntity
$emp:=ds.Employee.get(672)
$empCloned:=$emp.clone()

$emp.lastName:="Smith" //Updates done on $emp are not done on $empCloned

.diff()

History
ReleaseChanges
17Added

.diff( entityToCompare : 4D.Entity { ; attributesToCompare : Collection } ) : Collection

ParameterTypeDescription
entityToCompare4D.Entity->Entity to be compared with the original entity
attributesToCompareCollection->Name of attributes to be compared
ResultCollection<-Differences between the entities

Description

The .diff() function compares the contents of two entities and returns their differences.

In entityToCompare, pass the entity to be compared to the original entity.

In attributesToCompare, you can designate specific attributes to compare. If provided, the comparison is done only on the specified attributes. If not provided, all differences between the entities are returned.

The differences are returned as a collection of objects whose properties are:

Property nameTypeDescription
attributeNameTextName of the attribute
valueany - Depends on attribute typeValue of the attribute in the entity
otherValueany - Depends on attribute typeValue of the attribute in entityToCompare

Only attributes with different values are included in the collection. If no differences are found, .diff() returns an empty collection.

The function applies for properties whose kind is storage or relatedEntity. In case a related entity has been updated (meaning the foreign key), the name of the related entity and its primary key name are returned as attributeName properties (value and otherValue are empty for the related entity name).

If one of the compared entities is Null, an error is raised.

Example 1

 var $diff1; $diff2 : Collection
employee:=ds.Employee.query("ID=1001").first()
$clone:=employee.clone()

employee.firstName:="MARIE"
employee.lastName:="SOPHIE"
employee.salary:=500
$diff1:=$clone.diff(employee) // All differences are returned
$diff2:=$clone.diff(employee;New collection"firstName";"lastName"))
// Only differences on firstName and lastName are returned

$diff1:

[
{
"attributeName": "firstName",
"value": "Natasha",
"otherValue": "MARIE"
},
{
"attributeName": "lastName",
"value": "Locke",
"otherValue": "SOPHIE"
},
{
"attributeName": "salary",
"value": 66600,
"otherValue": 500
}
]
$diff2:

[
{
"attributeName": "firstName",
"value": "Natasha",
"otherValue": "MARIE"
},
{
"attributeName": "lastName",
"value": "Locke",
"otherValue": "SOPHIE"
}
]

Example 2

 var vCompareResult1; vCompareResult2; vCompareResult3; $attributesToInspect : Collection
vCompareResult1:=New collection
vCompareResult2:=New collection
vCompareResult3:=New collection
$attributesToInspect:=New collection

$e1:=ds.Employee.get(636)
$e2:=ds.Employee.get(636)

$e1.firstName:=$e1.firstName+" update"
$e1.lastName:=$e1.lastName+" update"

$c:=ds.Company.get(117)
$e1.employer:=$c
$e2.salary:=100

$attributesToInspect.push("firstName")
$attributesToInspect.push("lastName")

vCompareResult1:=$e1.diff($e2)
vCompareResult2:=$e1.diff($e2;$attributesToInspect)
vCompareResult3:=$e1.diff($e2;$e1.touchedAttributes())

vCompareResult1 (all differences are returned):

[
{
"attributeName": "firstName",
"value": "Karla update",
"otherValue": "Karla"
},
{
"attributeName": "lastName",
"value": "Marrero update",
"otherValue": "Marrero"
},
{
"attributeName": "salary",
"value": 33500,
"otherValue": 100
},
{
"attributeName": "employerID",
"value": 117,
"otherValue": 118
},
{
"attributeName": "employer",
"value": "[object Entity]",// Entity 117 from Company
"otherValue": "[object Entity]"// Entity 118 from Company
}
]

vCompareResult2 (only differences on $attributesToInspect are returned)

[
{
"attributeName": "firstName",
"value": "Karla update",
"otherValue": "Karla"
},
{
"attributeName": "lastName",
"value": "Marrero update",
"otherValue": "Marrero"
}
]

vCompareResult3 (only differences on $e1 touched attributes are returned)

[
{
"attributeName": "firstName",
"value": "Karla update",
"otherValue": "Karla"
},
{
"attributeName": "lastName",
"value": "Marrero update",
"otherValue": "Marrero"
},
{
"attributeName": "employerID",
"value": 117,
"otherValue": 118
},
{
"attributeName": "employer",
"value": "[object Entity]",// Entity 117 from Company
"otherValue": "[object Entity]"// Entity 118 from Company

}
]

.drop()

History
ReleaseChanges
17Added

.drop( {mode : Integer} ) : Object

ParameterTypeDescription
modeInteger->dk force drop if stamp changed: Forces the drop even if the stamp has changed
ResultObject<-Result of drop operation

Description

The .drop() function deletes the data contained in the entity from the datastore, from the table related to its Dataclass. Note that the entity remains in memory.

In a multi-user or multi-process application, the .drop() function is executed under an "optimistic lock" mechanism, wherein an internal locking stamp is automatically incremented each time the record is saved.

By default, if the mode parameter is omitted, the function will return an error (see below) if the same entity was modified (i.e. the stamp has changed) by another process or user in the meantime.

Otherwise, you can pass the dk force drop if stamp changed option in the mode parameter: in this case, the entity is dropped even if the stamp has changed (and the primary key is still the same).

Result

The object returned by .drop( ) contains the following properties:

PropertyTypeDescription
successbooleantrue if the drop action is successful, false otherwise.
Available only in case of error:
status(*)numberError code, see below
statusText(*)textDescription of the error, see below
Available only in case of pessimistic lock error:
LockKindTexttext"Locked by record"
lockInfoobjectInformation about the lock origin
task_idnumberProcess id
user_nametextSession user name on the machine
user4d_aliastextUser alias if defined by SET USER ALIAS, otherwise user name in the 4D directory
host_nametextMachine name
task_nametextProcess name
client_versiontext
Available only in case of serious error (serious error can be trying to duplicate a primary key, disk full...):
errorscollection of objects
messagetextError message
component signaturetextinternal component signature (e.g. "dmbg" stands for the database component)
errCodenumberError code

(*) The following values can be returned in the status and statusText properties of Result object in case of error:

ConstantValueComment
dk status entity does not exist anymore5The entity no longer exists in the data. This error can occur in the following cases:
  • the entity has been dropped (the stamp has changed and the memory space is now free)
  • the entity has been dropped and replaced by another one with another primary key (the stamp has changed and a new entity now uses the memory space). When using entity.drop( ), this error can be returned when dk force drop if stamp changed option is used. When using entity.lock( ), this error can be returned when dk reload if stamp changed option is used
  • Associated statusText: "Entity does not exist anymore"
    dk status locked3The entity is locked by a pessimistic lock.
    Associated statusText: "Already locked"
    dk status serious error4A serious error is a low-level database error (e.g. duplicated key), a hardware error, etc.
    Associated statusText: "Other error"
    dk status stamp has changed2The internal stamp value of the entity does not match the one of the entity stored in the data (optimistic lock).
  • with .save( ): error only if the dk auto merge option is not used
  • with .drop( ): error only if the dk force drop if stamp changed option is not used
  • with .lock( ): error only if the dk reload if stamp changed option is not used
  • Associated statusText: "Stamp has changed"
  • Example 1

    Example without dk force drop if stamp changed option:

     var $employees : cs.EmployeeSelection
    var $employee : cs.EmployeeEntity
    var $status : Object
    $employees:=ds.Employee.query("lastName=:1";"Smith")
    $employee:=$employees.first()
    $status:=$employee.drop()
    Case of
    :($status.success)
    ALERT("You have dropped "+$employee.firstName+" "+$employee.lastName) //The dropped entity remains in memory
    :($status.status=dk status stamp has changed)
    ALERT($status.statusText)
    End case

    Example 2

    Example with dk force drop if stamp changed option:

     var $employees : cs.EmployeeSelection
    var $employee : cs.EmployeeEntity
    var $status : Object
    $employees:=ds.Employee.query("lastName=:1";"Smith")
    $employee:=$employees.first()
    $status:=$employee.drop(dk force drop if stamp changed)
    Case of
    :($status.success)
    ALERT("You have dropped "+$employee.firstName+" "+$employee.lastName) //The dropped entity remains in memory
    :($status.status=dk status entity does not exist anymore)
    ALERT($status.statusText)
    End case

    .first()

    History
    ReleaseChanges
    17Added

    .first(): 4D.Entity

    ParameterTypeDescription
    Result4D.Entity<-Reference to first entity of an entity selection (Null if not found)

    Description

    The .first() function returns a reference to the entity in first position of the entity selection which the entity belongs to.

    If the entity does not belong to any existing entity selection (i.e. .getSelection( ) returns Null), the function returns a Null value.

    Example

     var $employees : cs.EmployeeSelection
    var $employee; $firstEmployee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName = :1";"H@") //This entity selection contains 3 entities
    $employee:=$employees[2]
    $firstEmployee:=$employee.first() //$firstEmployee is the first entity of the $employees entity selection

    .fromObject()

    History
    ReleaseChanges
    17Added

    .fromObject( filler : Object )

    ParameterTypeDescription
    fillerObject->Object from which to fill the entity

    Description

    The .fromObject() function fills an entity with the filler content.

    This function modifies the original entity.

    The mapping between the object and the entity is done on the attribute names:

    • If a property of the object does not exist in the dataclass, it is ignored.
    • Data types must be equivalent. If there is a type mismatch between the object and dataclass, 4D tries to convert the data whenever possible (see Converting data types), otherwise the attribute is left untouched.
    • The primary key can be given as is or with a "__KEY" property (filled with the primary key value). If it does not already exist in the dataclass, the entity is created with the given value when .save() is called. If the primary key is not given, the entity is created and the primary key value is assigned with respect to database rules. The auto-increment is only computed if the primary key is null.

    filler can handle a related entity under the following conditions:

    • filler contains the foreign key itself, or
    • filler contains a property object with the same name as the related entity, containing a single property named "__KEY".
    • if the related entity does not exist, it is ignored.

    Example

    With the following $o object:

    {
    "firstName": "Mary",
    "lastName": "Smith",
    "salary": 36500,
    "birthDate": "1958-10-27T00:00:00.000Z",
    "woman": true,
    "managerID": 411,// relatedEntity given with PK
    "employerID": 20 // relatedEntity given with PK
    }

    The following code will create an entity with manager and employer related entities.

     var $o : Object
    var $entity : cs.EmpEntity
    $entity:=ds.Emp.new()
    $entity.fromObject($o)
    $entity.save()

    You could also use a related entity given as an object:


    {
    "firstName": "Marie",
    "lastName": "Lechat",
    "salary": 68400,
    "birthDate": "1971-09-03T00:00:00.000Z",
    "woman": false,
    "employer": {// relatedEntity given as an object
    "__KEY": "21"
    },
    "manager": {// relatedEntity given as an object
    "__KEY": "411"
    }
    }

    .getDataClass()

    History
    ReleaseChanges
    17 R5Added

    .getDataClass() : 4D.DataClass

    ParameterTypeDescription
    Result4D.DataClass<-DataClass object to which the entity belongs

    Description

    The .getDataClass() function returns the dataclass of the entity. This function is useful when writing generic code.

    Example

    The following generic code duplicates any entity:

      //duplicate_entity method
    //duplicate_entity($entity)

    #DECLARE($entity : 4D.Entity)
    var $entityNew : 4D.Entity
    var $status : Object

    $entityNew:=$entity.getDataClass().new() //create a new entity in the parent dataclass
    $entityNew.fromObject($entity.toObject()) //get all attributes
    $entityNew[$entity.getDataClass().getInfo().primaryKey]:=Null //reset the primary key
    $status:=$entityNew.save() //save the duplicated entity

    .getKey()

    History
    ReleaseChanges
    17Added

    .getKey( { mode : Integer } ) : Text
    .getKey( { mode : Integer } ) : Integer

    ParameterTypeDescription
    modeInteger->dk key as string: primary key is returned as a string, no matter the primary key type
    ResultText<-Value of the text primary key of the entity
    ResultInteger<-Value of the numeric primary key of the entity

    Description

    The .getKey() function returns the primary key value of the entity.

    Primary keys can be numbers (Integer) or strings. You can "force" the returned primary key value to be a string, no matter the actual primary key type, by passing the dk key as string option in the mode parameter.

    Example

     var $employees : cs.EmployeeSelection
    var $employee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName=:1";"Smith")
    $employee:=$employees[0]
    ALERT("The primary key is "+$employee.getKey(dk key as string))

    .getSelection()

    History
    ReleaseChanges
    17Added

    .getSelection(): 4D.EntitySelection

    ParameterTypeDescription
    Result4D.EntitySelection<-Entity selection to which the entity belongs (Null if not found)

    Description

    The .getSelection() function returns the entity selection which the entity belongs to.

    If the entity does not belong to an entity selection, the function returns Null.

    Example

     var $emp : cs.EmployeeEntity
    var $employees; $employees2 : cs.EmployeeSelection
    $emp:=ds.Employee.get(672) // This entity does not belong to any entity selection
    $employees:=$emp.getSelection() // $employees is Null

    $employees2:=ds.Employee.query("lastName=:1";"Smith") //This entity selection contains 6 entities
    $emp:=$employees2[0] // This entity belongs to an entity selection

    ALERT("The entity selection contains "+String($emp.getSelection().length)+" entities")

    .getStamp()

    History
    ReleaseChanges
    17Added

    .getStamp() : Integer

    ParameterTypeDescription
    ResultInteger<-Stamp of the entity (0 if entity has just been created)

    Description

    The .getStamp() function returns the current value of the stamp of the entity.

    The internal stamp is automatically incremented by 4D each time the entity is saved. It manages concurrent user access and modifications to the same entities (see Entity locking).

    For a new entity (never saved), the function returns 0. To know if an entity has just been created, it is recommended to use .isNew().

    Example

     var $entity : cs.EmployeeEntity
    var $stamp : Integer

    $entity:=ds.Employee.new()
    $entity.lastname:="Smith"
    $entity.save()
    $stamp:=$entity.getStamp() //$stamp=1

    $entity.lastname:="Wesson"
    $entity.save()
    $stamp:=$entity.getStamp() //$stamp=2

    .indexOf()

    History
    ReleaseChanges
    17Added

    .indexOf( { entitySelection : 4D.EntitySelection } ) : Integer

    ParameterTypeDescription
    entitySelection4D.EntitySelection->Position of the entity is given according to this entity selection
    ResultInteger<-Position of the entity in an entity selection

    Description

    The .indexOf() function returns the position of the entity in an entity selection.

    By default if the entitySelection parameter is omitted, the function returns the entity's position within its own entity selection. Otherwise, it returns the position of the entity within the specified entitySelection.

    The resulting value is included between 0 and the length of the entity selection -1.

    • If the entity does not have an entity selection or does not belong to entitySelection, the function returns -1.
    • If entitySelection is Null or does not belong to the same dataclass as the entity, an error is raised.

    Example

     var $employees : cs.EmployeeSelection
    var $employee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName = :1";"H@") //This entity selection contains 3 entities
    $employee:=$employees[1] //This entity belongs to an entity selection
    ALERT("The index of the entity in its own entity selection is "+String($employee.indexOf())) //1

    $employee:=ds.Employee.get(725) //This entity does not belong to an entity selection
    ALERT("The index of the entity is "+String($employee.indexOf())) // -1

    .isNew()

    History
    ReleaseChanges
    17Added

    .isNew() : Boolean

    ParameterTypeDescription
    ResultBoolean<-True if entity has just been created and not yet saved. Otherwise, False.

    Description

    The .isNew() function returns True if the entity to which it is applied has just been created and has not yet been saved in the datastore. Otherwise, it returns False.

    Example

     var $emp : cs.EmployeeEntity

    $emp:=ds.Employee.new()

    If($emp.isNew())
    ALERT("This is a new entity")
    End if

    .last()

    History
    ReleaseChanges
    17Added

    .last() : 4D.Entity

    ParameterTypeDescription
    Result4D.Entity<-Reference to last entity of an entity selection (Null if not found)

    Description

    The .last() function returns a reference to the entity in last position of the entity selection which the entity belongs to.

    If the entity does not belong to any existing entity selection (i.e. .getSelection( ) returns Null), the function returns a Null value.

    Example

     var $employees : cs.EmployeeSelection
    var $employee; $lastEmployee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName = :1";"H@") //This entity selection contains 3 entities
    $employee:=$employees[0]
    $lastEmployee:=$employee.last() //$lastEmployee is the last entity of the $employees entity selection

    .lock()

    History
    ReleaseChanges
    17Added

    .lock( { mode : Integer } ) : Object

    ParameterTypeDescription
    modeInteger->dk reload if stamp changed: Reload before locking if stamp changed
    ResultObject<-Result of lock operation

    Description

    The .lock() function puts a pessimistic lock on the record referenced by the entity. The lock is set for a record and all the references of the entity in the current process.

    Other processes will see this record as locked (the result.success property will contain False if they try to lock the same entity using this function). Only functions executed in the "locking" session are allowed to edit and save the attributes of the entity. The entity can be loaded as read-only by other sessions, but they will not be able to enter and save values.

    A locked record is unlocked:

    • when the unlock() function is called on a matching entity in the same process
    • automatically, when it is no longer referenced by any entities in memory. For example, if the lock is put only on one local reference of an entity, the entity is unlocked when the function ends. As long as there are references to the entity in memory, the record remains locked.

    By default, if the mode parameter is omitted, the function will return an error (see below) if the same entity was modified (i.e. the stamp has changed) by another process or user in the meantime.

    Otherwise, you can pass the dk reload if stamp changed option in the mode parameter: in this case, no error is returned and the entity is reloaded when the stamp has changed (if the entity still exists and the primary key is still the same).

    Result

    The object returned by .lock( ) contains the following properties:

    PropertyTypeDescription
    successbooleantrue if the lock action is successful (or if the entity is already locked in the current process), false otherwise.
    Available only if dk reload if stamp changed option is used:
    wasReloadedbooleantrue if the entity was reloaded with success, false otherwise.
    Available only in case of error:
    status(*)numberError code, see below
    statusText(*)textDescription of the error, see below
    Available only in case of pessimistic lock error:
    lockKindTexttext"Locked by record"
    lockInfoobjectInformation about the lock origin
    task_idnumberProcess ID
    user_nametextSession user name on the machine
    user4d_aliastextName or alias of the 4D user
    user4d_idnumberUser id in the 4D database directory
    host_nametextMachine name
    task_nametextProcess name
    client_versiontext
    Available only in case of serious error (primary key already exists, disk full...):
    errorscollection of objects
    messagetextError message
    component signaturetextinternal component signature (e.g. "dmbg" stands for the database component)
    errCodenumberError code

    (*) The following values can be returned in the status and statusText properties of the Result object in case of error:

    ConstantValueComment
    dk status entity does not exist anymore5The entity no longer exists in the data. This error can occur in the following cases:
  • the entity has been dropped (the stamp has changed and the memory space is now free)
  • the entity has been dropped and replaced by another one with another primary key (the stamp has changed and a new entity now uses the memory space). When using .drop( ), this error can be returned when dk force drop if stamp changed option is used. When using .lock( ), this error can be returned when dk reload if stamp changed option is used

  • Associated statusText: "Entity does not exist anymore"
    dk status locked3The entity is locked by a pessimistic lock.Associated statusText: "Already locked"
    dk status serious error4A serious error is a low-level database error (e.g. duplicated key), a hardware error, etc.Associated statusText: "Other error"
    dk status stamp has changed2The internal stamp value of the entity does not match the one of the entity stored in the data (optimistic lock).
  • with .save( ): error only if the dk auto merge option is not used
  • with .drop( ): error only if the dk force drop if stamp changed option is not used
  • with .lock( ): error only if the dk reload if stamp changed option is not used

  • Associated statusText: "Stamp has changed"

    Example 1

    Example with error:

     var $employee : cs.EmployeeEntity
    var $status : Object
    $employee:=ds.Employee.get(716)
    $status:=$employee.lock()
    Case of
    :($status.success)
    ALERT("You have locked "+$employee.firstName+" "+$employee.lastName)
    :($status.status=dk status stamp has changed)
    ALERT($status.statusText)
    End case

    Example 2

    Example with dk reload if stamp changed option:

     var $employee : cs.EmployeeEntity
    var $status : Object
    $employee:=ds.Employee.get(717)
    $status:=$employee.lock(dk reload if stamp changed)
    Case of
    :($status.success)
    ALERT("You have locked "+$employee.firstName+" "+$employee.lastName)
    :($status.status=dk status entity does not exist anymore)
    ALERT($status.statusText)
    End case

    .next()

    History
    ReleaseChanges
    17Added

    .next() : 4D.Entity

    ParameterTypeDescription
    Result4D.Entity<-Reference to next entity in the entity selection (Null if not found)

    Description

    The .next() function returns a reference to the next entity in the entity selection which the entity belongs to.

    If the entity does not belong to any existing entity selection (i.e. .getSelection() returns Null), the function returns a Null value.

    If there is no valid next entity in the entity selection (i.e. you are on the last entity of the selection), the function returns Null. If the next entity has been dropped, the function returns the next valid entity (and eventually Null).

    Example

     var $employees : cs.EmployeeSelection
    var $employee; $nextEmployee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName = :1";"H@") //This entity selection contains 3 entities
    $employee:=$employees[0]
    $nextEmployee:=$employee.next() //$nextEmployee is the second entity of the $employees entity selection

    .previous()

    History
    ReleaseChanges
    17Added

    .previous() : 4D.Entity

    ParameterTypeDescription
    Result4D.Entity<-Reference to previous entity in the entity selection (Null if not found)

    Description

    The .previous() function returns a reference to the previous entity in the entity selection which the entity belongs to.

    If the entity does not belong to any existing entity selection (i.e. .getSelection() returns Null), the function returns a Null value.

    If there is no valid previous entity in the entity selection (i.e. you are on the first entity of the selection), the function returns Null. If the previous entity has been dropped, the function returns the previous valid entity (and eventually Null).

    Example

     var $employees : cs.EmployeeSelection
    var $employee; $previousEmployee : cs.EmployeeEntity
    $employees:=ds.Employee.query("lastName = :1";"H@") //This entity selection contains 3 entities
    $employee:=$employees[1]
    $previousEmployee:=$employee.previous() //$previousEmployee is the first entity of the $employees entity selection

    .reload()

    History
    ReleaseChanges
    17Added

    .reload() : Object

    ParameterTypeDescription
    ResultObject<-Status object

    Description

    The .reload() function reloads the content of the entity in memory, according to information stored in the table related to the dataclass in the datastore. The reload is done only if the entity still exists with the same primary key.

    Result

    The object returned by .reload( ) contains the following properties:

    PropertyTypeDescription
    successbooleanTrue if the reload action is successful, False otherwise.Available only in case of error:
    status(*)numberError code, see below
    statusText(*)textDescription of the error, see below

    (*) The following values can be returned in the status and statusText properties of Result object in case of error:

    ConstantValueComment
    dk status entity does not exist anymore5The entity no longer exists in the data. This error can occur in the following cases:
  • the entity has been dropped (the stamp has changed and the memory space is now free)
  • the entity has been dropped and replaced by another one with another primary key (the stamp has changed and a new entity now uses the memory space). When using .drop( ), this error can be returned when dk force drop if stamp changed option is used. When using .lock( ), this error can be returned when dk reload if stamp changed option is used

  • Associated statusText: "Entity does not exist anymore"
    dk status serious error4A serious error is a low-level database error (e.g. duplicated key), a hardware error, etc.
    Associated statusText: "Other error"

    Example

     var $employee : cs.EmployeeEntity
    var $employees : cs.EmployeeSelection
    var $result : Object

    $employees:=ds.Employee.query("lastName=:1";"Hollis")
    $employee:=$employees[0]
    $employee.firstName:="Mary"
    $result:=$employee.reload()
    Case of
    :($result.success)
    ALERT("Reload has been done")
    :($result.status=dk status entity does not exist anymore)
    ALERT("The entity has been dropped")
    End case

    .save()

    History
    ReleaseChanges
    17Added

    .save( { mode : Integer } ) : Object

    ParameterTypeDescription
    modeInteger->dk auto merge: Enables the automatic merge mode
    ResultObject<-Result of save operation

    Description

    The .save() function saves the changes made to the entity in the table related to its dataClass. You must call this method after creating or modifying an entity if you want to save the changes made to it.

    The save operation is executed only if at least one entity attribute has been "touched" (see the .touched() and .touchedAttributes() functions). Otherwise, the function does nothing (the trigger is not called).

    In a multi-user or multi-process application, the .save() function is executed under an "optimistic lock" mechanism, wherein an internal locking stamp is automatically incremented each time the record is saved.

    By default, if the mode parameter is omitted, the method will return an error (see below) whenever the same entity has been modified by another process or user in the meantime, no matter the modified attribute(s).

    Otherwise, you can pass the dk auto merge option in the mode parameter: when the automatic merge mode is enabled, a modification done concurrently by another process/user on the same entity but on a different attribute will not result in an error. The resulting data saved in the entity will be the combination (the "merge") of all non-concurrent modifications (if modifications were applied to the same attribute, the save fails and an error is returned, even with the auto merge mode).

    The automatic merge mode is not available for attributes of Picture, Object, and Text type when stored outside of the record. Concurrent changes in these attributes will result in a dk status stamp has changed error.

    Result

    The object returned by .save() contains the following properties:

    PropertyTypeDescription
    successbooleanTrue if the save action is successful, False otherwise.
    Available only if dk auto merge option is used:
    autoMergedbooleanTrue if an auto merge was done, False otherwise.
    Available only in case of error:
    statusnumberError code, see below
    statusTexttextDescription of the error, see below
    Available only in case of pessimistic lock error:
    lockKindTexttext"Locked by record"
    lockInfoobjectInformation about the lock origin
    task_idnumberProcess id
    user_nametextSession user name on the machine
    user4d_aliastextUser alias if defined by SET USER ALIAS, otherwise user name in the 4D directory
    host_nametextMachine name
    task_nametextProcess name
    client_versiontext
    Available only in case of serious error (serious error - can be trying to duplicate a primary key, disk full...):
    errorscollection of objects
    messagetextError message
    componentSignaturetextInternal component signature (e.g. "dmbg" stands for the database component)
    errCodenumberError code
    status and statusText

    The following values can be returned in the status and statusText properties of Result object in case of error:

    ConstantValueComment
    dk status automerge failed6(Only if the dk auto merge option is used) The automatic merge option failed when saving the entity.Associated statusText: "Auto merge failed"
    dk status entity does not exist anymore5The entity no longer exists in the data. This error can occur in the following cases:
  • the entity has been dropped (the stamp has changed and the memory space is now free)
  • the entity has been dropped and replaced by another one with another primary key (the stamp has changed and a new entity now uses the memory space). When using .drop( ), this error can be returned when dk force drop if stamp changed option is used. When using .lock( ), this error can be returned when dk reload if stamp changed option is used

  • Associated statusText: "Entity doesnot exist anymore"
    dk status locked3The entity is locked by a pessimistic lock.Associated statusText: "Already locked"
    dk status serious error4A serious error is a low-level database error (e.g. duplicated key), a hardware error, etc.Associated statusText: "Other error"
    dk status stamp has changed2The internal stamp value of the entity does not match the one of the entity stored in the data (optimistic lock).
  • with .save( ): error only if the dk auto merge option is not used
  • with .drop( ): error only if the dk force drop if stamp changed option is not used
  • with .lock( ): error only if the dk reload if stamp changed option is not used

  • Associated statusText: "Stamp has changed"

    Example 1

    Creating a new entity:

     var $status : Object
    var $employee : cs.EmployeeEntity
    $employee:=ds.Employee.new()
    $employee.firstName:="Mary"
    $employee.lastName:="Smith"
    $status:=$employee.save()
    If($status.success)
    ALERT("Employee created")
    End if

    Example 2

    Updating an entity without dk auto merge option:

     var $status : Object
    var $employee : cs.EmployeeEntity
    var $employees : cs.EmployeeSelection
    $employees:=ds.Employee.query("lastName=:1";"Smith")
    $employee:=$employees.first()
    $employee.lastName:="Mac Arthur"
    $status:=$employee.save()
    Case of
    :($status.success)
    ALERT("Employee updated")
    :($status.status=dk status stamp has changed)
    ALERT($status.statusText)
    End case

    Example 3

    Updating an entity with dk auto merge option:

     var $status : Object

    var $employee : cs.EmployeeEntity
    var $employees : cs.EmployeeSelection

    $employees:=ds.Employee.query("lastName=:1";"Smith")
    $employee:=$employees.first()
    $employee.lastName:="Mac Arthur"
    $status:=$employee.save(dk auto merge)
    Case of
    :($status.success)
    ALERT("Employee updated")
    :($status.status=dk status automerge failed)
    ALERT($status.statusText)
    End case

    .toObject()

    History
    ReleaseChanges
    17Added

    .toObject() : Object
    .toObject( filterString : Text { ; options : Integer} ) : Object
    .toObject( filterCol : Collection { ; options : Integer } ) : Object

    ParameterTypeDescription
    filterStringText->Attribute(s) to extract (comma-separated string)
    filterColCollection->Collection of attribute(s) to extract
    optionsInteger->dk with primary key: adds the _KEY property;
    dk with stamp: adds the _STAMP property
    ResultObject<-Object built from the entity

    Description

    The .toObject() function returns an object which has been built from the entity. Property names in the object match attribute names of the entity.

    If no filter is specified, or if the filterString parameter contains an empty string or "*", the returned object will contain:

    • all storage entity attributes
    • attributes of the relatedEntity kind: you get a property with the same name as the related entity (name of the many-to-one link). Attribute is extracted with the simple form.
    • attributes of the relatedEntities kind: attribute is not returned.

    In the first parameter, you pass the entity attribute(s) to extract. You can pass:

    • filterString: a string with property paths separated with commas: "propertyPath1, propertyPath2, ...", or
    • filterCol: a collection of strings: ["propertyPath1","propertyPath2";...]

    If a filter is specified for attributes of the relatedEntity kind:

    • propertyPath = "relatedEntity" -> it is extracted with simple form: an object with property __KEY (primary key).
    • propertyPath = "relatedEntity.*" -> all the properties are extracted
    • propertyPath = "relatedEntity.propertyName1; relatedEntity.propertyName2; ..." -> only those properties are extracted

    If a filter is specified for attributes of the relatedEntities kind:

    • propertyPath = "relatedEntities.*" -> all the properties are extracted
    • propertyPath = "relatedEntities.propertyName1; relatedEntities.propertyName2; ..." -> only those properties are extracted

    In the options parameter, you can pass the dk with primary key and/ordk with stamp selector(s) to add the entity's primary keys and/or stamps in extracted objects.

    Example 1

    The following structure will be used throughout all examples of this section:

    Without filter parameter:

    employeeObject:=employeeSelected.toObject()

    Returns:

    {
    "ID": 413,
    "firstName": "Greg",
    "lastName": "Wahl",
    "salary": 0,
    "birthDate": "1963-02-01T00:00:00.000Z",
    "woman": false,
    "managerID": 412,
    "employerID": 20,
    "photo": "[object Picture]",
    "extra": null,
    "employer": { // relatedEntity extracted with simple form
    "__KEY": 20
    },
    "manager": {
    "__KEY": 412
    }
    }

    Example 2

    Extracting the primary key and the stamp:

    employeeObject:=employeeSelected.toObject("";dk with primary key+dk with stamp)

    Returns:

    {
    "__KEY": 413,
    "__STAMP": 1,
    "ID": 413,
    "firstName": "Greg",
    "lastName": "Wahl",
    "salary": 0,
    "birthDate": "1963-02-01T00:00:00.000Z",
    "woman": false,
    "managerID": 412,
    "employerID": 20,
    "photo": "[object Picture]",
    "extra": null,
    "employer": {
    "__KEY": 20
    },
    "manager": {
    "__KEY": 412
    }
    }

    Example 3

    Expanding all the properties of relatedEntities:

    employeeObject:=employeeSelected.toObject("directReports.*")
    {
    "directReports": [
    {
    "ID": 418,
    "firstName": "Lorena",
    "lastName": "Boothe",
    "salary": 44800,
    "birthDate": "1970-10-02T00:00:00.000Z",
    "woman": true,
    "managerID": 413,
    "employerID": 20,
    "photo": "[object Picture]",
    "extra": null,
    "employer": {
    "__KEY": 20
    },
    "manager": {
    "__KEY": 413
    }
    },
    {
    "ID": 419,
    "firstName": "Drew",
    "lastName": "Caudill",
    "salary": 41000,
    "birthDate": "2030-01-12T00:00:00.000Z",
    "woman": false,
    "managerID": 413,
    "employerID": 20,
    "photo": "[object Picture]",
    "extra": null,
    "employer": {
    "__KEY": 20
    },
    "manager": {
    "__KEY": 413
    }
    },
    {
    "ID": 420,
    "firstName": "Nathan",
    "lastName": "Gomes",
    "salary": 46300,
    "birthDate": "2010-05-29T00:00:00.000Z",
    "woman": false,
    "managerID": 413,
    "employerID": 20,
    "photo": "[object Picture]",
    "extra": null,
    "employer": {
    "__KEY": 20
    },
    "manager": {
    "__KEY": 413
    }
    }
    ]
    }

    Example 4

    Extracting some properties of relatedEntities:

     employeeObject:=employeeSelected.toObject("firstName, directReports.lastName")

    Returns:

    {
    "firstName": "Greg",
    "directReports": [
    {
    "lastName": "Boothe"
    },
    {
    "lastName": "Caudill"
    },
    {
    "lastName": "Gomes"
    }
    ]
    }

    Example 5

    Extracting a relatedEntity with simple form:

     $coll:=New collection("firstName";"employer")
    employeeObject:=employeeSelected.toObject($coll)

    Returns:

    {
    "firstName": "Greg",
    "employer": {
    "__KEY": 20
    }
    }

    Example 6

    Extracting all the properties of a relatedEntity:

     employeeObject:=employeeSelected.toObject("employer.*")

    Returns:

    {
    "employer": {
    "ID": 20,
    "name": "India Astral Secretary",
    "creationDate": "1984-08-25T00:00:00.000Z",
    "revenues": 12000000,
    "extra": null
    }
    }

    Example 7

    Extracting some properties of a relatedEntity:

     $col:=New collection
    $col.push("employer.name")
    $col.push("employer.revenues")
    employeeObject:=employeeSelected.toObject($col)

    Returns:

    {
    "employer": {
    "name": "India Astral Secretary",
    "revenues": 12000000
    }
    }

    .touched( )

    History
    ReleaseChanges
    17Added

    .touched() : Boolean

    ParameterTypeDescription
    ResultBoolean<-True if at least one entity attribute has been modified and not yet saved, else False

    Description

    The .touched() function tests whether or not an entity attribute has been modified since the entity was loaded into memory or saved.

    If an attribute has been modified or calculated, the function returns True, else it returns False. You can use this function to determine if you need to save the entity.

    This function returns False for a new entity that has just been created (with .new( )). Note however that if you use a function which calculates an attribute of the entity, the .touched() function will then return True. For example, if you call .getKey() to calculate the primary key, .touched() returns True.

    Example

    In this example, we check to see if it is necessary to save the entity:

     var $emp : cs.EmployeeEntity
    $emp:=ds.Employee.get(672)
    $emp.firstName:=$emp.firstName //Even if updated with the same value, the attribute is marked as touched

    If($emp.touched()) //if at least one of the attributes has been changed
    $emp.save()
    End if // otherwise, no need to save the entity

    .touchedAttributes( )

    History
    ReleaseChanges
    17Added

    .touchedAttributes() : Collection

    ParameterTypeDescription
    ResultCollection<-Names of touched attributes, or empty collection

    Description

    The .touchedAttributes() function returns the names of the attributes that have been modified since the entity was loaded into memory.

    This applies for attributes of the kind storage or relatedEntity.

    In the case of a related entity having been touched (i.e., the foreign key), the name of the related entity and its primary key's name are returned.

    If no entity attribute has been touched, the method returns an empty collection.

    Example 1

     var $touchedAttributes : Collection
    var $emp : cs.EmployeeEntity

    $touchedAttributes:=New collection
    $emp:=ds.Employee.get(725)
    $emp.firstName:=$emp.firstName //Even if updated with the same value, the attribute is marked as touched
    $emp.lastName:="Martin"
    $touchedAttributes:=$emp.touchedAttributes()
    //$touchedAttributes: ["firstName","lastName"]

    Example 2

     var $touchedAttributes : Collection
    var $emp : cs.EmployeeEntity
    var $company : cs.CompanyEntity

    $touchedAttributes:=New collection

    $emp:=ds.Employee.get(672)
    $emp.firstName:=$emp.firstName
    $emp.lastName:="Martin"

    $company:=ds.Company.get(121)
    $emp.employer:=$company

    $touchedAttributes:=$emp.touchedAttributes()

    //collection $touchedAttributes: ["firstName","lastName","employer","employerID"]

    In this case:

    • firstName and lastName have a storage kind
    • employer has a relatedEntity kind
    • employerID is the foreign key of the employer related entity

    .unlock()

    History
    ReleaseChanges
    17Added

    .unlock() : Object

    ParameterTypeDescription
    ResultObject<-Status object

    Description

    The .unlock() function removes the pessimistic lock on the record matching the entity in the datastore and table related to its dataclass.

    For more information, please refer to Entity locking section.

    A record is automatically unlocked when it is no longer referenced by any entities in the locking process (for example: if the lock is put only on one local reference of an entity, the entity and thus the record is unlocked when the process ends).

    When a record is locked, it must be unlocked from the locking process and on the entity reference which put the lock. For example:

     $e1:=ds.Emp.all()[0]
    $e2:=ds.Emp.all()[0]
    $res:=$e1.lock() //$res.success=true
    $res:=$e2.unlock() //$res.success=false
    $res:=$e1.unlock() //$res.success=true

    Result

    The object returned by .unlock() contains the following property:

    PropertyTypeDescription
    successBooleanTrue if the unlock action is successful, False otherwise. If the unlock is done on a dropped entity, on a non locked record, or on a record locked by another process or entity, success is False.

    Example

     var $employee : cs.EmployeeEntity
    var $status : Object

    $employee:=ds.Employee.get(725)
    $status:=$employee.lock()
    ... //processing
    $status:=$employee.unlock()
    If($status.success)
    ALERT("The entity is now unlocked")
    End if