RDF Client API

The RDF Client API provides a simple set of methods for creating and deleting stores, executing transactions and running queries. It should be used when the application needs to deal directly with RDF data. An RDF Client can connect to an embedded store or remotely to a running BrightstarDB instance.

Creating a client

The BrightstarService class provides a number of static methods that can be used to create a new client. The most general one takes a connection string as a parameter and returns a client object. The client implements the BrightstarDB.IBrightstarService interface.

The following example shows how to create a new service client using a connection string:

var client = BrightstarService.GetClient(

For more information about connection strings, please read the “Connection Strings” topic

Creating a Store

A new store can be creating using the following code:

string storeName = "Store_" + Guid.NewGuid();

Deleting a Store

Deleting a store is also straight forward:


Jobs and IJobInfo

In BrightstarDB, many operations are executed as jobs. A job is simply an asynchronous task that is processed by the BrightstarDB server. BrightstarDB maintains a queue of jobs for each store and each store will process its jobs one at a time.

In the API, the methods that run as jobs all return an IJobInfo result. This interface defines a number of properties that can be used to check the status of a job.

Property Name Description
JobId The unique identifier for the job. This can be used with the GetJobInfo method to retrieve updates about the job as it is processed.
Label A user-provided label for the job. This label can be set when the job is created.
JobPending A boolean flag that is true if the job is currently queued for execution.
JobStarted A boolean flag that is true if the job is currently being executed.
JobCompletedWithErrors A boolean flag that is true if the job has failed.
JobCompletedOk A boolean flag that is true if the job has completed successfully.
QueuedTime The date/time when the job was queued to be processed
StartTime The date/time when the job entered processing.
EndTime The date/time when the job completed processing.
ExceptionInfo If an error occurred, this property exposed the detailed exception information.

Typically calling one of these methods simply queues the job for update and returns an IJobInfo structure straight away (the exceptions are the ExecuteTransaction and ExecuteUpdate methods which by default will only return when the job has completed successfully or failed).

You can monitor the progress of a job by making a call to the GetJobInfo method on the client. There are two variants of GetJobInfo the first takes a store name and a job ID and returns the status of that specific job. The second takes a store name, an offset and a length and returns the status of the jobs in that portion of the queue.


Job status is not persisted by a store. This means that a server is restarted for any reason, all queued jobs and job information is lost. Additionally, job status records for completed (or failed) jobs may be periodically culled from the queue.

Therefore it is possible for GetJobInfo to fail to find the details of a previously submitted job in some circumstances.

Transactional Update

BrightstarDB supports a transactional update model that allows you to group together a collection of triples to remove and triples to add as a single atomic operation, that will either succeed and modify the store, or if it fails will leave the store unmodified.

A transaction is defined by creating a new instance of the BrightstarDB.Client.UpdateTransactionData class and setting its properties. The transaction is then executed by passing the UpdateTransactionData instance to the ExecuteTransaction() method on the client:

var transactionData = new UpdateTransactionData();

// ... set properties of transactionData here...

var jobInfo = client.ExecuteTransaction(storeName, transactionData);

By default the method will block until the job completes processing (either successfully or with errors). You can then check the value of the IJobInfo object returned for the job status and any exception details. Alternatively, you can pass false for the optional waitForCompletion parameter and the update job will be queued and the IJobInfo object returned straight away that you can then monitor asynchronously from your code. To provide a custom label for the job, you can pass the label string in to the optional label parameter.

Inserting Data

Data is added to the store by specifying the data to be added in N-Triples or N-Quads format on the InsertData property of the UpdateTransactionData class. Each triple or quad must be on a single line with no line breaks, a good way to do this is to use a StringBuilder and then using AppendLine() for each triple.

var addTriples = new StringBuilder();
addTriples.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/name> \\"BrightstarDB\\" .");
addTriples.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/categories/nosql> .");
addTriples.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/categories/.net> .");
addTriples.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/categories/rdf> .");

var transactionData = new UpdateTransactionData { InsertData = addTriples };

The ExecuteTransaction() method is used to insert the data into the store:

var jobInfo = client.ExecuteTransaction(storeName, transactionData);

Deleting Data

Deletion is done by defining a pattern that should matching the triples to be deleted. The following example deletes the triple that asserts that BrightstarDB is in the product category NoSQL:

var deletePatterns = "<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/categories/nosql> .";
var transactionData = new UpdateTransactionData { DeletePatterns = deletePatterns };
client.ExecuteTransaction(storeName, transactionData);

The identifier http://www.brightstardb.com/.well-known/model/wildcard is a wildcard match for any value, so the following example deletes all triples that have a subject of http://www.brightstardb.com/products/brightstar and a predicate of http://www.brightstardb.com/schemas/product/category:

var deletePatterns = "<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/.well-known/model/wildcard> .";
var transactionData = new UpdateTransactionData { DeletePatterns = deletePatterns };
var jobInfo = client.ExecuteTransaction(storeName, transactionData);


The string http://www.brightstardb.com/.well-known/model/wildcard is also defined as the constant string BrightstarDB.Constants.WildcardUri.

Conditional Updates

The execution of a transaction can be made conditional on certain triples existing in the store. This is done by specifying the triples or triple patterns to be matched on the ExistencePreconditions property of the UpdateTransactionData class.

The following example updates the productCode property of a resource only if its current value is 640:

var preconditions = new StringBuilder();
preconditions.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "640"^^<http://www.w3.org/2001/XMLSchema#integer> .");
var deletes = new StringBuilder();
deletes.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "640"^^<http://www.w3.org/2001/XMLSchema#integer> .");
var inserts = new StringBuilder();
inserts.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "973"^^<http://www.w3.org/2001/XMLSchema#integer> .");
var transactionData = new UpdateTransactionData {
      ExistencePreconditions = preconditions.ToString(),
      DeletePatterns = deletes.ToString(),
      InsertData = inserts.ToString() };
client.ExecuteTransaction(storeName, transactionData);

When a transaction contains condition triples, every triple specified in the preconditions must exist in the store before the transaction is applied. If one or more triples specified in the preconditions are not matched, the update will not be applied.

In addition to being able to specify triple patterns that must exist in the store, it is also possible to specify patterns that MUST NOT exist before the update is applied. As with the existence preconditions, a failure

The following example adds a productCode property to a resource, only if the resource currently does not have a productCode property:

var preconditions = new StringBuilder();
preconditions.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> <http://www.brightstardb.com/.well-known/model/wildcard> .");
var inserts = new StringBuilder();
inserts.AppendLine("<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "973"^^<http://www.w3.org/2001/XMLSchema#integer> .");
var transactionData = new UpdateTransactionData {
    NonexistencePreconditions = preconditions.ToString(),
    InsertData = inserts.ToString() };
client.ExecuteTransaction(storeName, transactionData);

Existence and non-existence preconditions may both be specified on a transaction, both are checked before applying the update.

Data Types

In the code above we used simple triples to add a string literal object to a subject, such as:

<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/name> "BrightstarDB"

Other data types can be specified for the object of a triple by using the ^^ syntax:

<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "640"^^<http://www.w3.org/2001/XMLSchema#integer> .
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/releaseDate> "2011-11-11 12:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/cost> "0.00"^^<http://www.w3.org/2001/XMLSchema#decimal> .

Updating Graphs

The ExecuteTransaction() method on the IBrightstarService interface accepts a parameter that defines the default graph URI. When this parameters is specified, all precondition triples are tested against that graph; all delete triple patterns are applied to that graph; and all addition triples are added to that graph:

// This code update the graph http://example.org/graph1
client.ExecuteTransaction(storeName, preconditions, deletePatterns, additions, "http://example.org/graph1");

In addition, the format that is parsed for preconditions, delete patterns and additions allows you to mix N-Triples and N-Quads formats together. N-Quads are simply N-Triples with a fourth URI identifier on the end that specifies the graph to be updated. When an N-Quad is encountered, its graph URI overrides that passed into the ExecuteTransaction() method. For example, in the following code, one triple is added to the graph “http://example.org/graphs/alice” and the other is added to the default graph (because no value is specified in the call to ExecuteTransaction():

var txn1Adds = new StringBuilder();
    @"<http://example.org/people/alice> <http://xmlns.com/foaf/0.1/name> ""Alice"" <http://example.org/graphs/alice> .");
txn1Adds.AppendLine(@"<http://example.org/people/bob> <http://xmlns.com/foaf/0.1/name> ""Bob"" .");
var result = client.ExecuteTransaction(storeName, null, null, txn1Adds.ToString());


The wildcard URI is also supported for the graph URI in delete patterns, allowing you to delete matching patterns from all graphs in the BrightstarDB store.

Querying data using SPARQL

BrightstarDB supports SPARQL 1.1 for querying the data in the store. A simple query on the N-Triples above that returns all categories that the subject called “Brightstar DB” is connected to would look like this:

var query = "SELECT ?category WHERE { " +
        "<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> ?category " +

This string query can then be used by the ExecuteQuery() method to create an XDocument from the SPARQL results (See SPARQL XML Query Results Format for format of the XML document returned).

var result = XDocument.Load(client.ExecuteQuery(storeName, query));

BrightstarDB also supports several different formats for SPARQL results. The default format is XML, but you can also add a BrightstarDB.SparqlResultsFormat parameter to the ExecuteQuery method to control the format and encoding of the results set. For example:

var jsonResult = client.ExecuteQuery(storeName, query, SparqlResultsFormat.Json);

By default results are returned using UTF-8 encoding; however you can override this default behaviour by using the WithEncoding() method on the SparqlResultsFormat class. The WithEncoding() method takes a System.Text.Encoding instance and returns a SparqlResultsFormat instance that will ask for that specific encoding:

var unicodeXmlResult = client.ExecuteQuery(
                         storeName, query,

SPARQL queries that use the CONSTRUCT or DESCRIBE keywords return an RDF graph rather than a SPARQL results set. By default results are returned as RDF/XML using a UTF-8 format, but this can also be overridden by passing in an BrightstarDB.RdfFormat value for the graphFormat parameters:

var ntriplesResult = client.ExecuteQuery(
                       storeName, query, // where query is a CONSTRUCT or DESCRIBE

Querying Graphs

By default a SPARQL query will be executed against the default graph in the BrightstarDB store (that is, the graph in the store whose identifier is http://www.brightstardb.com/.well-known/model/defaultgraph). In SPARQL terms, this means that the default graph of the dataset consists of just the default graph in the store. You can override this default behaviour by passing the identifier of one or more graphs to the ExecuteQuery() method. There are two overrides of ExecuteQuery() that allow this. One accepts a single graph identifier as a string parameter, the other accepts multiple graph identifiers as an IEnumerable<string> parameter. The three different approaches are shown below:

// Execute query using the store's default graph as the default graph
var result = client.ExecuteQuery(storeName, query);

// Execute query using the graph http://example.org/graphs/1 as
// the default graph
var result = client.ExecuteQuery(storeName, query,

// Execute query using the graphs http://example.org/graphs/1 and
// http://example.org/graphs/2 as the default graph
var result = client.ExecuteQuery(storeName, query,
                                 new string[] {


It is also possible to use the FROM and FROM NAMED keywords in the SPARQL query to define both the default graph and the named graphs used in your query.

Using extension methods

To make working with the resulting XDocument easier there exist a number of extensions methods. The method SparqlResultRows() returns an enumeration of XElement instances where each XElement represents a single result row in the SPARQL results.

The GetColumnValue() method takes the name of the SPARQL result column and returns the value as a string. There are also methods to test if the object is a literal, and to retrieve the data type and language code.

foreach (var sparqlResultRow in result.SparqlResultRows())
   var val = sparqlResultRow.GetColumnValue("category");
   Console.WriteLine("Category is " + val);

Update data using SPARQL

BrightstarDB supports SPARQL 1.1 Update for updating data in the store. An update operation is submitted to BrightstarDB as a job. By default the call to ExecuteUpdate() will block until the update job completes:

IJobInfo jobInfo = _client.ExecuteUpdate(storeName, updateExpression);

In this case, the resulting IJobInfo object will describe the final state of the update job. However, you can also run the job asynchronously by passing false for the optional waitForCompletion parameter:

IJobInfo jobInfo = _client.ExecuteUpdate(storeName, updateExpression, false);

In this case the resulting IJobInfo object will describe the current state of the update job and you can use calls to GetJobInfo() to poll the job for its current status.

From version 1.11, BrightstarDB now supports the use of the BrightstarDB-specific wildcard IRI (http://www.brightstardb.com/.well-known/model/wildcard) in the DELETE and DELETE DATA clauses of a SPARQL Update command. The following example uses the wildcard IRI to specify a deletion of all tags from a given article:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX : <http://www.brightstardb.com/example/article#>
  <http://www.brightstardb.com/example/article/1433424821849> :tags <http://www.brightstardb.com/.well-known/model/wildcard>  .

It is possible to use the wildcard IRI in the subject, predicate or object positions of a triple. In the object position, the wildcard will match all literal values as well as all resources and blank nodes.

Data Imports

To support the loading of large data sets BrightstarDB provides an import function. Before invoking the import function via the client API the data to be imported should be copied into a folder called ‘import’. The ‘import’ folder should be located in the folder containing the BrigtstarDB store data folders. After a default installation the stores folder is [INSTALLDIR]\Data, thus the import folder should be [INSTALLDIR]\Data\import. For information about the RDF syntaxes that BrightstarDB supports for import, please refer to Supported RDF Syntaxes.

With the data copied into the folder the following client method can be called. The parameter is the name of the file that was copied into the import folder. You can optionally specify the default graph for the data to be imported into, and the format that the data is in. Import is executed asynchronously - the client will return an IJobInfo instance to allow you to monitor the progress of the job. See Jobs and IJobInfo for more information about managing asynchronous jobs.


// Import the NTriples data into the default graph in "mystore"
var importJob = client.StartImport("mystore", "data.nt");

// Import the RDF/XML data into a specific graph in "mystore"
var importJob = client.StartImport("mystore", "data.rdf", "http://example.org/graphs/1", importFormat:RdfFormat.RdfXml);

Data Exports

BrightstarDB also supports the bulk export of triples from a store. You can choose either to export a single graph or all of the graphs in the store. You can choose to export in the formats listed in the table below.

For Single Graph For Full Store
NTriples NQuads

The exported data will be written to a file contained in the BrightstarDB import folder (the same path as used for data import). Export is executed asynchronously - the client will return an IJobInfo instance to allow you to monitor the progress of the job. See Jobs and IJobInfo for more information about managing asynchronous jobs.


// Export all graphs in "mystore" in default NQuads format
var exportAllJob = client.StartExport("mystore", "data.nq");

// Export a single graph in RDF/XML format
var exportGraphJob = client.StartExport("mystore", "data.rdf",
                 "http://example.org/graph/1", RdfFormat.RdfXml);

Introduction To N-Triples

N-Triples is a consistent and simple way to encode RDF triples. N-Triples is a line based format. Each N-Triples line encodes one RDF triple. Each line consists of the subject (a URI), followed  by whitespace, the predicate (a URI), more whitespace, and then the object (a URI or literal) followed by a dot and a new line. The encoding of the literal may include a datatype or language code as well as the value. URIs are enclosed in ‘<’ ‘>’ brackets. The formal definition of the N-Triples format can be found here.

The following are examples of N-Triples data:

# simple literal property
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/name> "Brightstar DB" .

# relationship between two resources
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/category> <http://www.brightstardb.com/categories/nosql> .

# A property with an integer value
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/productCode> "640"^^<http://www.w3.org/2001/XMLSchema#integer> .

# A property with a date/time value
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/releaseDate> "2011-11-11 12:00"^^<http://www.w3.org/2001/XMLSchema#dateTime> .

# A property with a decimal value
<http://www.brightstardb.com/products/brightstar> <http://www.brightstardb.com/schemas/product/cost> "0.00"^^<http://www.w3.org/2001/XMLSchema#decimal> .

Allowed Data Types

Data types are defined in terms of an identifier. Common data types use the XML Schema identifiers. The prefix of these is http://www.w3.org/2001/XMLSchema#. The common primitive datatypes are defined in the XML Schema specification.

Introduction To SPARQL

BrightstarDB is a triple store that implements the RDF and SPARQL standards. SPARQL, pronounced “sparkle”, is the query language developer by the W3C for querying RDF data. SPARQL primarily uses pattern matching as a query mechanism. A short example follows:

PREFIX ont: <http://www.brightstardb.com/schemas/>
SELECT ?name ?description WHERE {
  ?product a ont:Product .
  ?product ont:name ?name .
  ?product ont:description ?description .

This query is asking for all the names and descriptions of all products in the store.

SELECT is used to specify which bound variables should appear in the result set. The result of this query is a table with two columns, one called “name” and the other “description”.

The PREFIX notation is used so that the query itself is more readable. Full URIs can be used in the query. When included in the query directly URIs are enclosed by ‘<’ and ‘>’.

Variables are specified with the ‘?’ character in front of the variable name.

In the above example if a product did not have a description then it would not appear in the results even if it had a name. If the intended result was to retrieve all products with their name and the description if it existed then the OPTIONAL keyword can be used.

PREFIX ont: <http://www.brightstardb.com/schemas/>
SELECT ?name ?description WHERE {
  ?product a ont:Product .
  ?product ont:name ?name .

    ?product ont:description ?description .

For more information on SPARQL 1.1 and more tutorials the following resources are worth reading.