Data Object Layer

The Data Object Layer is a simple generic object wrapper for the underlying RDF data in any BrightstarDB store.

Data Objects are lightweight wrappers around sets of RDF triples in the underlying BrightstarDB store. They allow the developer to interact with the RDF data without requiring all information to be sent in N-Triple format.

For more information about the RDF layer of BrightstarDB, please read the RDF Client API section.

Creating a Data Object Context

The IDataObjectContext interface provides the methods for accessing BrightstarDB stores through the Data Object Layer. You can use this interface to list the available stores, to open existing stores and to create or delete stores. The following example shows how to create a new context using a connection string:

var context = BrightstarService.GetDataObjectContext("Type=rest;endpoint=http://localhost:8090/brightstar;");

The connection string defines the type of service you are connecting to. For the Data Object Context, the connection can be to an embedded instance of BrightstarDB; a connection to a BrightstarDB server over the HTTP REST interface; or a connection to another store using a DotNetRDF storage connector. For more information about connection strings, please refer to the section Connection Strings.

Using the IDataObjectContext

Once you have an IDataObjectContext, a new store can be creating using the CreateStore method:

IDataObjectStore myStore = context.CreateStore("MyStore");

CreateStore also accepts a number of optional parameters which are described in later sections.

Deleting a store is also straight forward - you just pass in the name of the store to be deleted:


To check if a store with a particular name already exists, use the DoesStoreExist() method:

// Create MyStore if it doesn't already exist
if (!context.DoesStoreExist("MyStore")) {

To open an existing store, use the OpenStore() method. This method will throw an exception if the named store does not exist, so it is a good idea to test for this first:

IDataObjectStore myStore;
if (context.DoesStoreExist("MyStore")) {
  myStore = context.OpenStore("MyStore");

Working With Data Objects

Data Objects can be created using the MakeDataObject() method on the IDataObjectStore:

var fred = store.MakeDataObject("");

The objects can be created by passing in a well formed URI as the identity, if no identity is given then one is automatically generated for it and can be accessed via its Identity property. A data object can be retrieved from the store using its URI identifier:

var fred = store.GetDataObject("");

If BrightstarDB does not hold any information about a given URI, then a data object is created for it and passed back. When the developer adds properties to it and saves it, the identity will be automatically added to BrightstarDB.


GetDataObject() will never return a null object. The data object consists of all the information that is held in BrightstarDB for a particular identity.

To set the value of a single property, use the SetProperty() method. The method requires an IDataObject instance that defines the type of the property being added, so this needs to be created first.:

var name = store.MakeDataObject("");
fred.SetProperty(name, "Fred Evans");

There is also a short-hand version that takes care of creating the IDataObject for the type, so the following is equivalent to the previous two-line example:

fred.SetProperty("", "Fred Evans");

Calling SetProperty() a second time will overwrite the previous value of the property:

fred.SetProperty("", "Fred Q. Evans");

If you want to add multiple properties of the same type use the AddProperty() method instead of SetProperty():

var mbox = store.MakeDataObject("");
fred.AddProperty(mbox, "");
fred.AddProperty(mbox, "");

A property value can either be a literal primitive type (supported C# primitive types are string, bool, DateTime, Date, double, int, float, long, byte, decimal, short, ubyte, ushort, uint, ulong, char and byte[]), or another IDataObject instance:

var alice = store.MakeDataObject("");
var knows = store.MakeDataObject("");
fred.AddProperty(knows, alice);

There is also a short-hand function for setting the RDF type property for a data object:

var person = store.MakeDataObject("");

A property can be removed from a data object using the RemoveProperty() method:

fred.RemoveProperty(mbox, "");

RemoveProperty() will only remove a property that matches exactly by type and value (and language code if specified). Alternatively to remove all properties of a given type, use the RemovePropertiesOfType() method:


All of these methods for adding/remove properties and setting a type return the data object itself, allowing the calls to be chained:

    .SetProperty(name, "Fred Q. Evans")
    .AddProperty(mbox, "")
    .AddProperty(knows, alice);

Adding and removing properties and changing the type simply adds and removes triples from the set of locally managed triples for the data object.

To retrieve property values use either the GetPropertyValues() method to retrieve an enumerator over all of the property values for a specific property type; or use the GetPropertyValue() method that returns just the first value of a specific type. These methods both take either an IDataObject instance or a string to identify the property type:

// Get a data object for the property type we are intersted in
var name = store.MakeDataObject("");
// Write all names of fred
foreach (var n in fred.GetPropertyValues(name)) {
// Write just one mbox of fred

To determine what properties a data object has, use the GetPropertyTypes() method to enumerate over the distinct types of property that a data object has. This can be useful for grouping together properties by type or for exploring / displaying data with an unknown schema behind it:

Console.WriteLine("Properties of Fred:");
foreach(var propertyType in fred.GetPropertyTypes()) {
    Console.WriteLine("\t" + propertyType.Identity + ":");
    foreach(var propertyValue in fred.GetPropertyValues(propertyType)) {
        Console.WriteLine("\t\t" + propertyValue);

A data object can be deleted using the Delete() method on the data object itself:

var fred = store.GetDataObject("");

This will remove all triples describing that data object from the store when changes are saved.

Updates such as new properties, new objects and deletions are all tracked by the IDataObjectStore locally and are only applied to the BrightstarDB store when you call the SaveChanges() method on the store. SaveChanges() saves your changes in a single transaction, so either all updates will be applied to the store or the transaction will fail and none of the updates will be applied.

Namespace Mappings

Namespace mappings are sets of simple string prefixes for URIs, enabling the developer to use identities that have been shortened to use the prefixes.

For example, the mapping:

{"people", ""}

Means that the short string “people:fred” will be expanded to the full identity string “”

These mappings are passed through as a dictionary to the OpenStore() method on the context:

_namespaceMappings = new Dictionary<string, string>()
                             {"people", ""},
                             {"skills", ""},
                             {"schema", ""}
store = context.OpenStore(storeName, _namespaceMappings);


It is best practise to set up a static dictionary within your class or configuration

Querying data using SPARQL

BrightstarDB supports SPARQL 1.1 for querying the data in the store. These queries can be executed via the Data Object store using the ExecuteSparql() method.

The SparqlResult returned has the results of the SPARQL query in the ResultSet property which is a dotNetRDF SparqlResultSet. For information about how to work with a SparqlResultSet, please see the dotNetRDF User Guide.

Binding SPARQL Results To Data Objects

When a SPARQL query has been written to return a single variable binding, it can be passed to the BindDataObjectsWithSparql() method. This executes the SPARQL query, and then binds each URI in the results to a data object, and passes back the enumeration of these instances:

var skillsQuery = "SELECT ?skill WHERE {?skill a <>}";
var allSkills = store.BindDataObjectsWithSparql(skillsQuery).ToList();
foreach (var s in allSkills)
    Console.WriteLine("Skill is " + s.Identity);


The BindDataObjectsWithSparql() method will execute the SPARQL query against the currently saved store. This means that any results received will not take into account local modifications or locally created new DataObjects until a call to SaveChanges() is made.

Optimistic Locking in the Data Object Layer

The Data Object Layer provides a basic level of optimistic locking support using the conditional update support provided by the RDF Client API and a special version property that gets assigned to data objects. Optimistic locking is enabled in one of two ways. The first option is to enable optimistic locking in the connection string used to create the IDataObjectContext:

var context = BrightstarService.GetDataObjectContext(

The other option is to enable optimistic locking in the OpenStore() or CreateStore() method used to retrieve the IDataObjectStore instance from the IDataObjectContext:

var store = context.OpenStore("MyStore", optimisticLockingEnabled:true);


The optimisticLockingEnabled parameter of OpenStore() and CreateStore() is optional. If it is omitted, then the setting in the connection string for the IDataObjectContext is used. If it is specified, it always overrides the setting in the connection string.

With optimistic locking enabled, the Data Object Layer checks for the presence of a special version property on every object it retrieves (the property predicate URI is If this property is present, its value defines the current version number of the property. If the property is not present, the object is recorded as being currently unversioned. On save, the Data Object Layer uses the current version number of all versioned data objects as the set of preconditions for the update, if any of these objects have had their version number property modified on the server, the precondition will fail and the update will not be applied. Also as part of the save, the Data Object Layer updates the version number of all versioned data objects and creates a new version number for all unversioned data objects.

When an concurrent modification is detected, this is notified to your code by a TransactionPreconditionsFailedException being raised. In your code you should catch this exception and handle the error. The IDataObjectStore interface provides a Refresh() method that implements two common approaches to handling this status. The Refresh() method takes two parameters: a data object instance and a RefreshMode parameter that specifies how the object is to be updated. RefreshMode.StoreWins overwrites any local modifications made to the object with the updated values held on the server. RefreshMode.ClientWins works the other way around, keeping the local changes and updating the version number for the locally tracked object so that the next time SaveChanges() is attempted the local changes will overwrite those held on the server. To find which objects need refreshing, the IDataObjectStore provides the TrackedObjects property that returns an enumerator over all the objects currently tracked by the store. Each IDataObject instance provides an IsModified property that is set to true if the store has some local changes for that object.

Graph Targeting in the Data Object API

You can use the Data Object API to update a specific named graph in the BrightstarDB store. Each time you open a store you can specify the following optional parameters:

  • updateGraph : The identifier of the graph that new statements will be added to.

    For connections to a BrightstarDB server, this defaults to the BrightstarDB default graph ( For connections through the DotNetRDF connectors, the default graph will be store and service dependent.

  • defaultDataSet : The identifier of the graphs that statements will be retrieved from.

    For connections to a BrightstarDB server, this defaults to all graphs in the store. For connections through the DotNetRDF connectors, the default data set will be store and service dependent.

  • versionGraph : The identifier of the graph that contains version information for

    optimistic locking. Defaults to the same graph as updateGraph.

These are passed as additional optional parameters to the IDataObjectContext.OpenStore() method.

To create a store that reads properties from the default graph and adds properties to a specific graph (e.g. for recording the results of inferences), use the following:

// Set storeName, prefixes and inferredGraphUri here
var store = context.OpenStore(storeName, prefixes, updateGraph:inferredGraphUri,
                              defaultDataSet: new[] {Constants.DefaultGraphUri},


Note that you need to be careful when using optimistic locking to ensure that you are consistent about which graph manages the version information. We recommend that you either use the BrightstarDB default graph (as shown in the example above) or use another named graph separate from the graphs that store the rest of the data (and define a constant for that graph URI).

To create a store that reads only the inferred properties use code like this:

// Set storeName, prefixes and inferredGraphUri here
var store = context.OpenStore(storeName, prefixes, updateGraph:inferredGraphUri,
                              defaultDataSet: new[] {inferredGraphUri},

When creating a new store using the IDataObjectContext.CreateStore() method the updateGraph and versionGraph options can be specified, but the defaultDataSet parameter is not available as a new store will not have any graphs. In this case the store returned will read from and write to the graph specified by the updateGraph parameter.

Default Data Set

The defaultDataSet parameter can be used to list the URIs of the graphs that should be queried by the IDataObjectStore returned by the method. In SPARQL parlance, this set of graphs is known as the dataset. If an update graph or version graph is specified then those graph URIs will also be added to the data set.

In the special case that updateGraph, versionGraph and defaultDataSet are all NULL (or not specified in the call to OpenStore), and the connection being opened is a connection to a BrightstarDB store the default data set will be set to cover all of the graphs in the BrightstarDB store.

When connecting to other stores using the DotNetRDF connectors, the default data set will be defined by the server unless the defaultDataSet parameter is explicitly set.

Graph Targeting and Deletions

The RemoveProperty() and SetProperty() methods can both cause triples to be deleted from the store. In this case the triples are removed from both the graph specified by updateGraph and all the graphs specified in the defaultDataSet (or all graphs in the store if the defaultDataSet is not specified or is set to null).

Similarly if you call the Delete method on a DataObject, the triples that have the DataObject as subject or object will be deleted from the updateGraph and all graphs in the defaultDataSet.