Summary: Understanding the semantics of Space Entries and .NET Objects
OverviewA data unit stored in the space is called an Entry. However, as you've seen in Writing Your First Application, there was no entry in the code - the program simply wrote a plain .NET object to the space and then took it. The API is .NET-friendly, and supports storing & retrieving .NET objects, which are transformed into space entries under the hood. For example, when the program wrote a Message object with a String property called Text, it was actually stored as an entry, whose type name was Message, which held one string property called Text. Most of the time, the terms object and entry are used interchangeably, because the meaning is clear from the context, and the semantics are trivial. However, it is important to understand the difference between them. Moreover, some features rely on applying semantics to an object to get a specific entry behavior. This page explains how objects are transformed to (and from) entries, and how that process can be controlled and customized.
Including/Excluding Data from an EntryBy default, all public members (fields and properties) in a class are included in the entry, whereas non-public members are excluded. Since the common design practice is to expose data via public properties that encapsulate protected/private fields, usually there's no need to adjust this behaviour. However, it can be adjusted for exceptional cases. Customizing a Specific ClassTo customize a specific class, apply a [SpaceClass] attribute on the class, and use IncludeProperties and/or IncludeFields to specify which members should be included in the entry. Both IncludeProperties and IncludeFields are an IncludeMembers enumeration, which can be set to one of the following:
Example 1.1 – The default behaviourpublic class Person {...}
This is actually equivalent to the following declaration: [SpaceClass(IncludeFields=IncludeMembers.Public, IncludeProperties=IncludeMembers.Public)]
public class Person {...}
Example 1.2 – To exclude all properties and include all fields, even private ones:[SpaceClass(IncludeFields=IncludeMembers.All, IncludeProperties=IncludeMembers.None)]
public class Person {...}
Customizing a Specific MemberTo customize a specific field/property, apply a [SpaceProperty] to include it, or a [SpaceExclude] to exclude it. These settings override the class-level settings. Example 1.3 – Storing all the Person properties except the Password propertypublic class Person { [SpaceExclude] public String Password {...} }
IndexingIf a property is used frequently when quering the space, you can instruct the space to index it for faster retrieval, by using the [SpaceProperty] attribute, and specifing Index=SpaceIndexType.Basic. For example: public class Person { [SpaceProperty(Index=SpaceIndexType.Basic)] public String UserID {...} }
Object ID vs. Entry IDThe ProblemExamine the following piece of code: Example 2Message message = new Message(); message.Text = "Same Same, But Different"; proxy.Write(message); proxy.Write(message); If you execute it, and examine the space in the GigaSpaces Management Center, you will see two different entries with the same text, even though from the .NET perspective, there's only one object. You should also see an additional column called UID, which is not part of our .NET object, and which contains a unique identifier that distinguishes the entries from each other. This unique identifier is commonly referred to as a Space ID. What happened behind the scenes? When a write operation executes, a new entry is created, and the properties are copied from the object to the entry. Each entry contains an additional special hidden UID property, which we ignored and left as null. When the space receives an entry to store, it verifies that there's no stored entry with the same UID, and if the UID is null, it generates a unique one. In our scenario, because the UID was ignored, the second write operation resulted in a separate entry containing the same data, with a different UID. So how do we utilize the Space ID? Exposing Generated Space IDLet's add the following piece of code – the Message class: private String _messageID; [SpaceID(AutoGenerate = true)] public String MessageID { get { return _messageID; } set { _messageID = value; } } If you run the code from example 2 again, you will see that the second write fails, with an EntryAlreayInSpaceException. If you examine the newly added MessageID property in the debugger, you will see that even though we didn't set it, it contains a unique identifier string. When a property is marked as [SpaceID(AutoGenerate = true)], it is mapped to the entry's UID. On the first write operation the MessageID was null, so the entry UID was null, and the space generated a UID for it. Before the operation was completed, the generated UID was copied back to the MessageID property, as the debugger shows. On the second write operation, the space again creates an entry, and maps the object data to the entry, but this time the MessageID is no longer empty, so the entry UID is not empty. The space checked if the UID is unique, discovered there's another entry with the same UID and aborted the operation. Next, we'll see how to make the space use the object when generating the UID. Controlling the Generated Space IDModify the SpaceID declaration from true to false: [SpaceID(AutoGenerate = false)] public String MessageID {...}
There are two modes of SpaceID that are supported:
The default is AutoGenerate=false. Note that only one property in a class can be marked as a SpaceID property.
Under the HoodEach public property/field in the object is mapped to a property of the same name and type in the entry. Non-public properties and fields are ignored. This means that any object can be stored in the space - it does not have to inherit from a specific base class, implement an interface, or have any attributes. The only requirement is to have a parameterless constructor (it doesn't have to be public), so the object can be created when being retrieved from the space. While this generic approach solves simple scenarios easily, in some cases it is not enough. For example, you may want to exclude a specific property from being stored in the space, or specify that a certain property should be indexed for faster performance. For that end, you can use a set of .NET attributes to control how an object is mapped to an entry. If you don't want to (or can't) use XAP.NET attributes in your code, you can create an xml file that defines those behaviors, commonly called gs.xml.
RoutingWhen working with a clustered space, one of the properties in a class is used to determine the routing behaviour of that class within the cluster (i.e. how instances of that class are partitioned across the cluster's nodes). The routing property is determined according to the following rules:
Note that only one property in a class can be marked as a routing property.
VersioningThe space can keep track of an object's version (i.e. how many times it was written/updated in the space), and provide optimistic concurrency using that version information. For that reason, the space needs to store the object's version in some property in the object. To specify that a property should be used for versioning, mark it with a [SpaceVersion] attribute. If no property is marked as a space version, the space does not store version information for that class. Note that only one property in a class can be marked as a version property, and it must be of type int. NullValueWhen a class contains a field or a property of not a nullable type, (for instance a primitive such as int or a struct such as DateTime), it is recommended to specify a null value for it that will be used when querying the space for that class. The NullValue attribute instructs the space to ignore this field, when performing matching or partial update, when the content of the field in the template equals the defined NullValue.
To specify a null value, the field or property should be marked with the [SpaceProperty(NullValue = ?)] attribute: Example 3.1 - Null value on a primitive intpublic class Person { [SpaceProperty(NullValue = -1)] public int Age {...} } Example 3.2 - Null value on DateTimepublic class Person { [SpaceProperty(NullValue = "1900-01-01T12:00:00")] public DateTime BornDate {...} } MappingBy default, the name of the class in the space is the fully-qualified class name (i.e. including namespace), and the properties/fields names in the space equal to the .NET name. In some cases, usually in interoperability scenarios, you may need to map your .NET class name and properties to different names in the space. You can do that using the AliasName property on [SpaceClass] and [SpaceProperty]. For example, the following .NET Person class contains mapping to an equivalent Java Person class: namespace MyCompany.MyProject { [SpaceClass(AliasName="com.mycompany.myproject.Person")] public class Person { [SpaceProperty(AliasName="firstName")] public String FirstName {...} } } For more information, see GigaSpaces.NET - Interoperability With Non .NET Applications.
PersistencyThe space can be attached to an external data source, and persist its classes through it. It can be specified whether a certain class should be persisted or not. To do this, use the [SpaceClass(Persist=true)] or [SpaceClass(Persist=false)] class level attribute. The default is [SpaceClass(Persist=true)]. [SpaceClass(Persist=false)] public class Person {...} ReplicationSome cluster toplogies have replication defined, which means that some or all of the data is replicated between the spaces. In this case, it can be specified whether each class should be replicated or not, by using the [SpaceClass(Replicate=true)] or [SpaceClass(Replicate=false)] class level attribute. The default is [SpaceClass(Replicate=true)]. [SpaceClass(Replicate=false)] public class Person {...} FIFOA class can be marked to operate in FIFO mode, which means that all the inserts, removals and notifications of this class should be done in First-in-First-out mode. It can be specified whether each class should operate in FIFO mode or not, by using the [SpaceClass(Fifo=true)] or [SpaceClass(Fifo=false)] class level attribute. The default is [SpaceClass(Fifo=false)]. [SpaceClass(Fifo=true)] public class Person {...} |
![]() |
GigaSpaces.com - Legal Notice - 3rd Party Licenses - Site Map - API Docs - Forum - Downloads - Blog - White Papers - Contact Tech Writing - Gen. by Atlassian Confluence |