EntityValue

open class EntityValue : StructureBase, BindingPath, EntityValueOrList

Encapsulates an OData entity value.

  • Decode the encoded data from the Decoder object and insantiate a new EntityValue object from it.

    See also

    EntityValue.encode(to encoder: Encoder) for usage examples how to encode and decode EntityValue

    Declaration

    Swift

    public required init(from decoder: Decoder) throws

    Parameters

    from

    decoder object which contains the original object’s serialized data in a container instance

  • Encode the object instance

    See also

    EntityValue.decode(to encoder: Encoder)

    Example of encode/decode of an EntityValue using proxy classes

    open func encodeEntityValueExample() throws -> Void {
    let provider = OnlineODataProvider(serviceName: "NorthwindService",
        serviceRoot: "http://services.odata.org/V4/Northwind/Northwind.svc/")
    let service = NorthwindService(provider: provider)
    
    // Download the entity by proxy classes which will be encoded
    let query = DataQuery()
    let entityValueToBeEncoded = try service.fetchEmployees(matching: query).first
    
    // Encode the EntityValue with JSONEncoder (other encoder exists such as PropertyListEncoder)
    let encoder = JSONEncoder()
    if let encodedEntityValue = try? encoder.encode(entityValueToBeEncoded) {
        if let json = String(data: encodedEntityValue, encoding: .utf8){
            print(json)
        }
    
        // Decoding
        // JSONDecoder is used, but other decoders are available, such as PropertyListDecoder
        let decoder = JSONDecoder()
        // Add typeInfo to the decoder
        decoder.userInfo[CSDLDocument.csdlInfoKey] = service.metadata
    
        // Decode
        let decodedEntityValue = try? decoder.decode(EntityValue.self,
            from: encodedEntityValue)
    }
    }
    

    Example of encode/decode of an EntityValue using dynamic API

    open func encodeEntityValueExample() throws -> Void {
        let provider = OnlineODataProvider(serviceName: "NorthwindService",
            serviceRoot: "http://services.odata.org/V4/Northwind/Northwind.svc/")
        let service = DataService(provider: provider)
    
        // Explicitly load metadata, it must be cached manually. The reason is that type infos
        // will not be implicitly encoded. The dataservice's metadata contains all such infos,
        // so it must be cached, and parsed later at decoding.
        service.serviceOptions.csdlOptions = ( service.serviceOptions.csdlOptions |
            CSDLOption.retainResolvedText | CSDLOption.retainOriginalText )
        try service.loadMetadata()
        let metadataCachedAsString = service.metadata.resolvedText!
    
        // Get the entity to be encoded by dynamic API
        let peopleEntitySet = try service.entitySet(withName: "Employees")
        let query = DataQuery().from(peopleEntitySet)
        let entityValueToBeEncoded = try service.executeQuery(query).entityList().first
    
        // Encode the EntityValue with JSONEncoder (other encoder exists such as PropertyListEncoder)
        let encoder = JSONEncoder()
        if let encodedEntityValue = try? encoder.encode(entityValueToBeEncoded) {
            if let json = String(data: encodedEntityValue, encoding: .utf8){
                print(json) // Check
            }
    
            // Decoding
            // JSONDecoder is used, but other decoders are available, such as PropertyListDecoder
            let decoder = JSONDecoder()
    
            // Get type infos from cached metadata by parsing it to CSDLDocument
            let parser: CSDLParser = CSDLParser()
            parser.csdlOptions = (CSDLOption.processMixedVersions | CSDLOption.retainOriginalText |
                CSDLOption.resolveUndefinedTerms)
            var csdlDocument: CSDLDocument = parser.parseInProxy(metadataCachedAsString, url: "")
    
            // Add typeInfo to the decoder
            decoder.userInfo[CSDLDocument.csdlInfoKey] = csdlDocument
    
            // Decode
            let decodedEntityValue = try? decoder.decode(EntityValue.self, from: encodedEntityValue)
        }
    }
    

    Declaration

    Swift

    public override func encode(to encoder: Encoder) throws

    Parameters

    to

    encoder object which can be used to serialize the object’s data one by one into a container instance

  • Flags for controlling updates, e.g. deep update.

    See also

    UpdateFlags.

    Declaration

    Swift

    final public var updateFlags: Int
  • Parent entity when this entity is to be created as a related child.

    Declaration

    Swift

    final public var parentEntity: EntityValue?
  • Parent property when this entity is to be created as a related child.

    Declaration

    Swift

    final public var parentProperty: Property?
  • Can be used to hold the “last modified time” for a changed entity.

    Declaration

    Swift

    final public var deltaTime: GlobalDateTime?
  • OData entity id (IRI) for this entity, preferably relative to the service root URL. If an entity does not have an explicit entity id, then callers should use the canonical URL.

    Declaration

    Swift

    final public var entityID: String?
  • Entity tag from backend system (may differ from entityTag for entities used with SQLDatabaseProvider).

    Declaration

    Swift

    final public var backendEtag: String?
  • The read link for this value, preferably relative to the service root URL. If an entity does not have an explicit read link, then readers should use the valuePath, or if that is not set, then a canonical URL (refer to the OData specification).

    Declaration

    Swift

    final public var readLink: String?
  • The edit link for this value, preferably relative to the service root URL. If an entity does not have an explicit edit link, then writers should use the valuePath, or if that is not set, then a canonical URL (refer to the OData specification).

    Declaration

    Swift

    final public var editLink: String?
  • A system-generated numeric key for this entity. Not guaranteed to be unique. For internal use. Should not be changed by application code.

    Declaration

    Swift

    final public var systemKey: Int64
  • Construct a new entity value. This constructor is intended for use by custom entity value subclasses. Use ofType for regular construction.

    Declaration

    Swift

    public init(withDefaults: Bool = false, type: EntityType? = nil, withIndexMap: SparseIndexMap? = nil)

    Parameters

    withDefaults

    Should setDefaultValues be called to initialize properties with default values?

    type

    Entity type. Should not be nil except when called by generated proxy base classes.

    withIndexMap

    If non-null, the created entities will use a sparse array implementation.

  • true if create/update/delete conflicts (duplicate key conflicts or optimistic concurrency conflicts) for this entity should not log/throw exceptions.

    Declaration

    Swift

    open var allowConflicts: Bool { get set }
  • Bind an entity to a property of the current entity. This can be used before DataService.createEntity or DataService.updateEntity to create or update the bindings of navigation properties.

    Example using proxy classes

    open func bindEntityExample() throws -> Void {
        let service = self.service
        let categoryQuery = DataQuery().top(1).expand(Category.products)
        let category = try service.fetchCategory(matching: categoryQuery)
        let productQuery = DataQuery().top(1)
        let product = try service.fetchProduct(matching: productQuery)
        category.bindEntity(product, to: Category.products)
        try service.updateEntity(category)
    }
    

    Example using dynamic API

    open func bindEntityExample() throws -> Void {
        let service = self.service
        let categoriesEntitySet = service.entitySet(withName: "Categories")
        let productsEntitySet = service.entitySet(withName: "Products")
        let categoryEntityType = categoriesEntitySet.entityType
        let productsProperty = categoryEntityType.property(withName: "Products")
        let categoryQuery = DataQuery().from(categoriesEntitySet).top(1)
            .expand(productsProperty)
        let category = try service.executeQuery(categoryQuery).requiredEntity()
        let productQuery = DataQuery().from(productsEntitySet).top(1)
        let product = try service.executeQuery(productQuery).requiredEntity()
        category.bindEntity(product, to: productsProperty)
        try service.updateEntity(category)
    }
    

    Declaration

    Swift

    open func bindEntity(_ entity: EntityValue, to: Property)

    Parameters

    entity

    Entity to be bound.

    to

    Property the entity will be bound to.

  • The canonical URL for this entity, relative to the service root URL. Uses OData V4 URL conventions.

    Declaration

    Swift

    open var canonicalURL: String { get }
  • Compare two entities for sorting by primary key.

    Declaration

    Swift

    open class func compareKeys(_ left: EntityValue?, _ right: EntityValue?) -> Int

    Parameters

    left

    First entity for comparison.

    right

    Second entity for comparison.

    Return Value

    A zero value if left is equal to right in sorted order, a negative value (e.g. -1) if left is less than right in sorted order, or a positive value (e.g. 1) if left is greater than right in sorted order.

  • Declaration

    Swift

    open func copyEntity() -> EntityValue

    Return Value

    A copy of this entity value (only structural properties are copied).

  • Copy structural/dynamic property values from source entity into this entity.

    Declaration

    Swift

    open func copyProperties(from: EntityValue)

    Parameters

    from

    Source entity.

  • Data type with a DataType.code of DataType.ENTITY_VALUE.

    Declaration

    Swift

    override open var dataType: DataType { get }
  • Should this entity’s children, if any, participate in a deep update? Enable this flag before calling DataService.updateEntity, or for convenience use withDeepUpdate. The flag will be cleared for this entity (and its children, if any) after a successful call to updateEntity, but will not be cleared if updateEntity fails.

    Declaration

    Swift

    open var deepUpdate: Bool { get set }
  • If deepUpdate is also true, should this entity’s children, if any, participate in a deep update cascading to nested entities? Can be combined with deepUpdateDelta. Enable this flag before calling DataService.updateEntity, The deep update will cascade to changed nested entities at any nesting level, such as those returned by a previous query using DataQuery.expand. The cascading will apply only to changed nested entities for which EntityValue.hasChangedPropertiesForUpdate returns true, as well as any intermediate entities on the path from this entity to the changed nested entities. The flag will be cleared for this entity (and its children, if any) after a successful call to updateEntity, but will not be cleared if updateEntity fails.

    Declaration

    Swift

    open var deepUpdateCascade: Bool { get set }
  • Is this entity a child in a deep update? This property is set automatically by DataService.updateEntity and is reserved for internal use.

    Declaration

    Swift

    open var deepUpdateChild: Bool { get set }
  • If deepUpdate is also true, should this entity’s children, if any, participate in a deep update using delta payload format? Can be combined with deepUpdateCascade. Enable this before calling DataService.updateEntity. The flag will be cleared for this entity (and its children, if any) after a successful call to updateEntity, but will not be cleared if updateEntity fails.

    Declaration

    Swift

    open var deepUpdateDelta: Bool { get set }
  • Is this entity a parent in a deep update? This property is set automatically by DataService.updateEntity and is reserved for internal use.

    Declaration

    Swift

    open var deepUpdateParent: Bool { get set }
  • The entity key for this value.

    Declaration

    Swift

    open var entityKey: EntityKey { get }
  • The entity set for this value.

    See also

    inSet.

    Declaration

    Swift

    open var entitySet: EntitySet { get set }
  • Server-generated entity tag for this entity. If non-null, it is used for conflict detection during DataService.updateEntity and DataService.deleteEntity calls.

    Declaration

    Swift

    open var entityTag: String? { get set }
  • The entity type metadata for this value (dataType cast to EntityType).

    Declaration

    Swift

    open var entityType: EntityType { get }
  • Declaration

    Swift

    open class func equal(_ left: EntityValue?, _ right: EntityValue?) -> Bool

    Parameters

    left

    First entity value.

    right

    Second entity value.

    Return Value

    true if two entity values have equal structural properties.

  • Declaration

    Swift

    open class func equalKeys(_ left: EntityValue?, _ right: EntityValue?) -> Bool

    Parameters

    left

    First entity value.

    right

    Second entity value.

    Return Value

    true if two entity values have equal key properties.

  • Set isDraft to true, and set the primary key for this entity to a value likely to be suitable for a local offline draft. For key properties of type int', this will be a value > 2000000000 offset by an amount determined from current UTC dateTime (month/day/hour/minute/second). For key properties of typelong’, this will be a value > 9000000000000000000 offset by an amount determined from current UTC dateTime (month/day/hour/minute/second). For key properties of type string', 'binary' or 'guid', this will be a random GUID value converted to the appropriate type. For key properties of typestring’ where the Property.maxLength is insufficient to hold a GUID (between 10 and 31 inclusive), then the value will be the string equivalent of the value that would be used for type ‘long’ or ‘int’, whichever should fit. For key properties of type binary' where theProperty.maxLength` is insufficient to hold a complete GUID (less than 16 bytes), then a random GUID value will be truncated to fit. Key properties of any other data type will not be set.

    Declaration

    Swift

    open func generateDraftKey()
  • true if this entity has binding-related changes.

    See also

    bindEntity, unbindEntity.

    Declaration

    Swift

    open var hasChangedBindings: Bool { get set }
  • true if a create/update/delete conflict was detected for this entity.

    Declaration

    Swift

    open var hasConflict: Bool { get set }
  • Declaration

    Swift

    open func hasKey() -> Bool

    Return Value

    true if this entity has a value for all key properties.

  • true if the entity is related to entities which are local (entities that have local requests executed that have either not been sent or have been sent but not yet downloaded).

    Declaration

    Swift

    open var hasLocalRelatives: Bool? { get set }
  • true if there are unsent requests in the request queue.

    Declaration

    Swift

    open var hasPendingChanges: Bool { get set }
  • true if the entity is related to entities that have unsent requests in the request queue.

    Declaration

    Swift

    open var hasRelativesWithPendingChanges: Bool? { get set }
  • true if this entity is in error state, for example due to the failed backend execution of an uploaded offline create/update/delete operation. If true, then one of isCreated, isUpdated or isDeleted should also be true to indicate the kind of failed operation. In some cases (e.g. system unable to distinguish create from update due to “upsert” behaviour) then isCreated, isUpdated and isDeleted might all be false.

    Declaration

    Swift

    open var inErrorState: Bool { get set }
  • Change the entity set for this entity. Having a non-null entity set is optional if only one entity set in the DataService uses the entity type, but is required (before DataService.createEntity is called) if multiple entity sets use the same entity type.

    Example using proxy classes

    open func createInSetExample() throws -> Void {
        let service = self.service
        let customer = Customer()
        customer.companyName = "Voyager Inc."
        customer.contactName = "Kathryn Janeway"
        try service.createEntity(customer.inSet(NorthwindService.customers))
    }
    

    Example using dynamic API

    open func createInSetExample() throws -> Void {
        let service = self.service
        let customersEntitySet = service.entitySet(withName: "Customers")
        let customerEntityType = customersEntitySet.entityType
        let companyNameProperty = customerEntityType.property(withName: "CompanyName")
        let contactNameProperty = customerEntityType.property(withName: "ContactName")
        let customer = EntityValue.ofType(customerEntityType)
        companyNameProperty.setStringValue(in: customer, to: "Voyager Inc.")
        contactNameProperty.setStringValue(in: customer, to: "Kathryn Janeway")
        try service.createEntity(customer.inSet(customersEntitySet))
    }
    

    Declaration

    Swift

    open func inSet(_ set: EntitySet) -> EntityValue

    Parameters

    set

    Entity set.

    Return Value

    This entity.

  • true if this object is an entity binding. The isReference property should also be true for bindings.

    See also

    bindEntity, unbindEntity.

    Declaration

    Swift

    open var isBinding: Bool { get set }
  • true if this entity has just been created in the local database or backend system.

    Declaration

    Swift

    open var isCreated: Bool { get set }
  • true if this entity has just been deleted from the local database or backend system.

    Declaration

    Swift

    open var isDeleted: Bool { get set }
  • true if this entity is in a draft state. To enable offline drafts with Mobile Back-End Tools (and Offline OData), add to the EntityType element in the CSDL XML metadata. To enable Fiori-style online drafts with CDS models, add the @odata.draft.enabled annotation to the CDS entity definition.`)

    Declaration

    Swift

    open var isDraft: Bool { get set }
  • true if a change (create, update or delete) has been submitted to the local database, but not yet synchronized to the backend system.

    Declaration

    Swift

    open var isLocal: Bool { get set }
  • true if this entity has been newly instantiated, but not yet created, updated or deleted in the local database or backend system.

    Declaration

    Swift

    open var isNew: Bool { get set }
  • Declaration

    Swift

    open func isNewOrChanged(property: Property) -> Bool

    Parameters

    property

    Structural property.

    Return Value

    true if the value of property property is new or changed, relative to oldEntity.

  • true if this object is an entity reference. If true, the editLink and/or readLink will be non-null, or the key properties will be available. Non-key properties will not be available.

    Declaration

    Swift

    open var isReference: Bool { get set }
  • ‘true’ if the entity was already resolved by CsdlDocument’s resolveEntity.

    Declaration

    Swift

    open var isResolved: Bool { get set }
  • ‘true’ if the entity is being resolved by CsdlDocument’s resolveEntity.

    Declaration

    Swift

    open var isResolving: Bool { get set }
  • true if this entity has just been updated in the local database or backend system.

    Declaration

    Swift

    open var isUpdated: Bool { get set }
  • ‘true’ if the entity is being upserted.

    Declaration

    Swift

    open var isUpsert: Bool { get set }
  • Stream link for media entities. Should not be used with non-media entities.

    Declaration

    Swift

    open var mediaStream: StreamLink { get set }
  • true if the entity must be modified by an update request, even if it is apparently unchanged. This ensures that DataService.updateEntity will force an update in the backend database/system.

    Declaration

    Swift

    open var mustBeModified: Bool { get set }
  • true if the entity state must be reloaded (via loadEntity) after a create/update request.

    Declaration

    Swift

    open var mustBeReloaded: Bool { get set }
  • true if operations on this entity should not be locally cascaded to children.

    Declaration

    Swift

    open var noLocalCascade: Bool { get set }
  • Construct a new entity value of the specified type.

    Declaration

    Swift

    open class func ofType(_ type: EntityType, sparse: SparseIndexMap? = nil) -> EntityValue

    Parameters

    type

    Entity type for the new value.

    sparse

    Sparse index map. For internal use.

    Return Value

    A new entity value.

  • Contains the original values for all structural properties of this entity value. Used by DataService.updateEntity to determine the changed properties for PATCH requests.

    Declaration

    Swift

    open var oldEntity: EntityValue? { get set }
  • Remember a snapshot of the values of structural/dynamic properties of this entity in oldEntity. Snapshots are used to detect which properties have changed when an update is to be issued.

    See also

    DataType.isMutable.

    Declaration

    Swift

    open func takeSnapshot(canDefer: Bool = false)

    Parameters

    canDefer

    Can the snapshot be deferred? This can improve query performance if queried entities are not subsequently updated. Defaults to false. Should only be true if all selected properties are immutable.

  • Convert this data value to a string. If the dataType is defined by XML Schema Part 2: Datatypes, then the corresponding lexical format is used. JSON format is used for structured values (arrays and objects).

    Declaration

    Swift

    override open func toString() -> String

    Return Value

    Lexical representation of this data value.

  • Data type code of the wrapped value, equivalent to dataType.code.

    Declaration

    Swift

    override open var typeCode: Int { get }
  • Unbind an entity from a property of the current entity. This can be used before DataService.createEntity or DataService.updateEntity to create or update the bindings of navigation properties.

    Example using proxy classes

    open func unbindEntityExample() throws -> Void {
        let service = self.service
        let categoryQuery = DataQuery().top(1).expand(Category.products)
        let category = try service.fetchCategory(matching: categoryQuery)
        let products = category.products
        if products.count != 0 {
            let product = products.first!
            category.unbindEntity(product, from: Category.products)
        }
        try service.updateEntity(category)
    }
    

    Example using dynamic API

    open func unbindEntityExample() throws -> Void {
        let service = self.service
        let categoriesEntitySet = service.entitySet(withName: "Categories")
        let categoryEntityType = categoriesEntitySet.entityType
        let productsProperty = categoryEntityType.property(withName: "Products")
        let categoryQuery = DataQuery().from(categoriesEntitySet).top(1)
            .expand(productsProperty)
        let category = try service.executeQuery(categoryQuery).requiredEntity()
        let products = productsProperty.entityList(from: category)
        if products.length != 0 {
            let product = products.first()
            category.unbindEntity(product, from: productsProperty)
        }
        try service.updateEntity(category)
    }
    

    Declaration

    Swift

    open func unbindEntity(_ entity: EntityValue?, from: Property, deleted: Bool = false)

    Parameters

    entity

    Entity to be unbound. Can be nil for unbinding an entity from a single-valued navigation property.

    from

    Property the entity will be unbound from.

    deleted

    Indicates that as well as being unbound from the current entity, the previously bound entity should be deleted.

  • true if the entity was not modified by an update request, because none of its properties were changed by the application before the attempt to update.

    Declaration

    Swift

    open var wasNotModified: Bool { get set }
  • Set deepUpdate to true, and return this entity instance.

    Example with proxy classes

    open func deepUpdateExample() throws -> Void {
        let service = self.service
        let query = DataQuery().top(1).filter(Customer.contactName.equal("Beverly Crusher"))
        let customer = try service.fetchCustomer(matching: query)
        let orders = customer.orders
        let firstOrder = orders[0]
        let nextOrder = orders[1]
        let newOrder = Order()
        newOrder.orderDate = GlobalDateTime.now()
        customer.unbindEntity(firstOrder, from: Customer.orders)
        nextOrder.requiredDate = GlobalDateTime.now().plusDays(7)
        customer.bindEntity(newOrder, to: Customer.orders)
        customer.deepUpdateDelta = true
        try service.updateEntity(customer.withDeepUpdate())
    }
    

    Declaration

    Swift

    open func withDeepUpdate() -> EntityValue

    Return Value

    This entity instance.

  • Change the primary key for this entity.

    Declaration

    Swift

    open func withKey(_ key: EntityKey) -> EntityValue

    Parameters

    key

    Primary key

    Return Value

    This entity.

  • Perform some work within an instance-level exclusive lock.

    Declaration

    Swift

    open func withLock(work: @escaping () -> Void)

    Parameters

    work

    Work to be executed within an instance-level exclusive lock.