Trinity

Easily develop Linked Data applications that integrate into your existing software eco-system.

  • MIT License
  • Cross-platform
  • .NET 3.5 / Mono 2.6

Enterprise Semantic Web Platform for C#

Trinity is an application development platform for Microsoft .NET and Mono. It allows to easily build Linked Data and Semantic Web applications based on the RDF metadata standard issued by the W3C. The API allows for developing first-class .NET applications with direct access to Linked Open Data repositories and knowledge bases such as DBPedia, Freebase, Geonames, BBC Business News, BBC Sports and many more.

The platform is built on top of the powerful and stable dotNetRDF library which has been in development since early 2009. Since dotNetRDF is low-level and primarliy focused on directly manipulating triples, it does not integrate well with existing application frameworks and introduces a steep learning curve for new developers.

Our primary goal was to allow developers to use proven enterprise development patterns such as MVC or MVVM to build Linked Data applications that integrate well into modern application eco-systems, such as:

Benefits

Semiodesk Trinity is based on the Resource Description Framework (RDF) linked data platform, which is an open standard maintained by the World Wide Web Consortium (W3C). This means your data is vendor-independent and will be easily accessible and exchangable in many years to come. Compared to many propriety graph databases, it has some considerable advantages:

Standardized Graph Data Model

RDF extends the linking structure of the Word Wide Web to name things and the relationships between them. Using this simple model, it allows structured and semi-structured data to be mixed, exposed, and shared across different applications.

  • Flexible schema evolution
  • Powerful data merging

Ontologies: Class & Property Inheritance

Ontologies provide a powerful way to describe classes and their properties in RDF. In contrast to many established data modelling frameworks, ontologies also allow to define inheritance relationships amongst properties. Since ontologies are part of the data graph, this can happen during application rutime.

  • Enterprise data integration
  • Run-Time data model changes

Powerful & Intuitive Query Language

The SPARQL query language is in terms very similar to SQL, but allows queries to be formulated in the Subject-Predicate-Object sentence structure of most western natural languages. This makes it feel familiar almost immediately and introduces a shallow learning cuve.
Learn more..

  • Complex queries made simple
  • Shallow learning curve

Logical Inferencing

Ontologies provide rich knowledge about data structure, such as sub-class, sub-property hierarchies and about the transitivity of properties. Many RDF databases can make use of logical reasoning during application runtime to answer queries about facts which have not been explicitly saved.

  • Discover unknown data relationships
  • Highly storage efficient

Features

Semiodesk Trinty provides the following features that allow you to build rock solid Linked Data applications using proven enterprise development patterns. Click on the topics below to learn more about a specific feature:

The Semiodesk Trinity platform allows to use ontology terms directly in the IDE, supporting code completion such as IntelliSense in Microsoft Visual Studio. This feature does not only eliminate the risk for typing errors in the program, but also allows for discovering the terms which are defined in an ontology directly from the code editor.

///<summary>
/// The Nepomuk Contact Ontology describes contact information, common in many places on the desktop. ...
///</summary>
public class nco : Ontology
{
...

///<summary>
/// A Contact that denotes a Person. A person can have multiple Affiliations.
///<see cref="http://www.semanticdesktop.org/ontologies/2007/03/22/nco#PersonContact"/>
///</summary>
public static readonly Class PersonContact = new Class(new Uri("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#PersonContact"));

///<summary>
/// To specify the formatted text corresponding to the name of the object the Contact represents. ...
///<see cref="http://www.semanticdesktop.org/ontologies/2007/03/22/nco#fullname"/>
///</summary>
public static readonly Property fullname = new Property(new Uri("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#fullname"));

...
}
				

The terms in the vocabularies are typed according to their definition in the ontology. This means, that properties and classes are assigned corresponding .NET CLR types which allow the compiler to detect possible errors in their usage. For example, it is not possible to pass classes or other terms as argumens to the AddProperty() method of resources.

Sometimes it necessary to access the terms of ontologies as compile time constants. In example, when being used in property attributes of .NET objects. To address this issue, we generate an additional vocaublary class which contains the terms of the ontology as compile-time constants. These classes are named after their namespace prefix in uppercase:

///<summary>...</summary>
public static class NCO
{
...

///<summary>...</summary>
public const string PersonContact = "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#PersonContact";

///<summary>...</summary>
public const string Property fullname = "http://www.semanticdesktop.org/ontologies/2007/03/22/nco#fullname";

...
}
				

We have developed tools to help you use the classes and properties wich are defined in ontologies directly in your project. A source code generator transforms RDFS and OWL ontologies into C# representations for use in the source code. Another tool deploys the ontologies to your triple store, synchronizing the ontologies used for dynamic query inferencing with the ones in your code repository.

This toolchain can be integrated into your build process which allows you to stay up to date and detect possible program errors as your ontologies change. We have prepared a small example to show the advantages of these tools.

Similar to OR-mapping techniques for relational databases, we provide a way to map RDFS / OWL terms to .NET objects. Using byte-code manipulation, we implement the code required for the mapping during program compilation. This results in higher performance and less runtime errors than solutions based on introspection.

// A class mapping to PersonContact in the NEPOMUK Contact Ontology.
[RdfClass(NCO.PersonContact)]
public class Contact : Resource
{
[RdfProperty(NCO.fullname)]
public string Fullname { get; set; }

[RdfProperty(NCO.birthday)]
public DateTime Birthday { get; set; }
}

This makes creating new resources and setting their properties a breeze. In the following example, we illustrate how easy it is to create a new contact object and commit it to the database as RDF triples:

// Create new contact with GUID
Contact c = model.CreateResource<Contact>();
c.Birthday = new DateTime(1985, 6, 17);
c.Fullname = "John Doe";
c.Commit();

Additional to the convenience it brings, the mapping also lets you utilize the type inheritance of RDF in your C# classes. Suppose you have PersonContact and CompanyContact resources in your model, both are derived from the Contact class. With Trinity you can query for the base type and you will get all derived types in your results as well. Use the power of inheritance in your data modelling!

For more information about the mapping mechanism, check out the Wiki pages.

Many modern UI development frameworks support binding the value of properties directly to controls. This allows for rapid application development and greatly increases the flexibility of prototyped interfaces. Mapped properties support a one-way data binding (from object to user interface) for most of the UI toolkits available for the .NET platform, including ASP.NET MVC applications.

Some frameworks, such as Windows Forms and WPF, also support bi-directional data binding through the INotifyPropertyChanged interface. Semiodesk Trinity provides a conventient way to implement value change notification through property attributes. This way, data objects can directly be manipulated from the UI with the need for extra glue code:

// A class mapping to PersonContact in the NEPOMUK Contact Ontology.
[RdfClass(NCO.PersonContact)]
public class Contact : Resource
{
// Raises the NotifyPropertyChanged-event when the property value changes.
[RdfProperty(NCO.fullname), NotifyPropertyChanged]
public string Fullname { get; set; }

// Raises the CollectionChanged-event when the collection is modified.
[RdfProperty(FOAF.knows)]
public ObservableCollection<PersonContact> Connections { get; private set; }
}

In RDF graphs, resources can be connected to a potentially large number of other resources. For example, a person can easily have hundereds of contacts in their addressbook. In order to maintain application performance in such scenarios, mapped properties feature a lazy loading mechanism where related objects are only loaded when they are accessed.

// A class mapping to PersonContact in the NEPOMUK Contact Ontology.
[RdfClass(NCO.PersonContact)]
public class Contact : Resource
{
[RdfProperty(FOAF.knows)]
public List<PersonContact> Connections { get; private set; }
}

For user interfaces to stay responsive, it is necessary to load the data asynchronously. We employ a data virtualization strategy to mitigate that problem for the application developer. With this the data can be visualized step-by-step as it comes from the data store:

// Asynchronously load 100 items per page
AsyncVirtualizingResourceCollection result = new AsyncVirtualizingResourceCollection(model, query, 100);

foreach (PersonContact c in result.GetResources<PersonContact>())
{
Console.WriteLine(c.Fullname);
}

To make it even easier to retrive whole objects from the RDF database, we have implemented a special query interface which allows for formulating queries for resources in code. The ResourceQuery-API aids in formulating the queries leveraging the code-completion mechanism of your IDE.

// A contact group named 'Familiy'.
ResourceQuery group = new ResourceQuery(nco.ContactGroup);
group.Where(nco.contactGroupName, "Family");

// A contact who belongs to the 'Familiy'-group and was born before Jan 1st 1990.
ResourceQuery contact = new ResourceQuery(nco.PersonContact);
contact.Where(nco.birthDate).LessThan(new DateTime(1990, 1, 1));
contact.Where(nco.belongsToGroup, group);

IResourceQueryResult result = model.ExecuteQuery(contact);

foreach (PersonContact c in result.GetResources<PersonContact>())
{
Console.WriteLine(c.Fullname);
}

The Trinity API currently has built-in support for three store types:

  1. OpenLink Virtuoso via ADO.NET
    Recommended for scalable, high-performance applications up to a billion triples per instance.
  2. SPARQL Protocol Endpoints
    Recommended for connecting with 3rd party triple stores.
  3. In-Memory
    Recommended for quickly accessing the contents of files or unit tests.

If you want to see the differences between these stores check out the examples.

Getting Started

Developing Linked Data applications with the Semiodesk Trinity platform is easy. Simply choose your preferred development environment and follow the instructions to get everything set up for you. If you are new to Linked Data in general, we recommend you to have a look at our example applications as a first step. Enjoy!

Setup

  1. Create a new Visual Studio Solution
  2. Add the Semiodesk Trinity Modelling NuGet package
  3. Add your ontologies
  4. Start creating the data model of your application

Minimum System Requirements

  • Windows 7 / 8 / 10
  • .NET Framework 3.5
  • Visual Studio 2010

Setup

  1. Create a new Xamarin Studio Solution
  2. Add the Semiodesk Trinity Modelling NuGet package
  3. Include the file 'Ontologies.g.cs' from the folder 'Ontologies' into the Project
  4. Add your ontologies
  5. Start creating the data model of your application

Minimum System Requirements

  • Windows 7 / 8 / 10 or Mac OS X 10.6+
  • .NET Framework 3.5 or Mono 2.6
  • Xamarin Studio 5+

Documentation

Please visit our Bitbucket project page for the complete API reference and example applications.

License

The library and tools in this repository are all released under the terms of the MIT license. This means you can use it for all kinds of projects – including commercial ones – as long as you keep the copyright header intact. The source code, documentation and issue tracking can be found at our Bitbucket project page. If you like what we are doing and want to support us, please consider donating.

Technical Support

If you encounter problems with Semiodesk Trinity you can use our issue tracking system. If you are interested in priority support or need some technical expertise, you can contact us under hello@semiodesk.com or through the contact page.

Please join our public mailing list to ask questions and for sharing ideas of any kind.

Community & Contributing

We'd like to encourage anyone who is interested in using or contributing to Trinity to join our public mailing list for discussing anything related to this project. If you want to contribute source code, please make sure that you have all the rights for publication under a MIT license and create a pull request at our Bitbucket project site.