This document will guide you through creating a simple application that allows you to access RDF data in a Virtuoso database as an Entity DataSet and explore that RDF data in an intuitive way by clicking on dereferenceable IRIs.
demo_dav.vad
) and install it.
The VAD package will create a new database in Virtuoso called demo containing the familiar Northwind tables.
It will also creates Linked Data Views of the Northwind tables.
In the example we assume the database is accessible on a hostname of "demo.openlinksw.com
" on the default port 80
, where an actually live instance of the Virtuoso Demo database is hosted.
Users would use the appropriate hostname and port number of their Virtuoso installation to create the sample application, and would be localhost:8890
for a default installation or whatever the URIQA DefaultHost
Virtuoso configuration parameter is set to when the demo database VAD package is installed.We want to be able to access the RDF data in Visual Studio and the easiest way to do this is to create a view of the data that we are interested in and bind that view to a DataSet. This can be considered as using server side SPARQL. Virtuoso supports an extension to standard SQL that allows execution of SPARQL within a SQL statement. If a SQL query begins with the keyword SPARQL then the rest of the query is interpreted by as SPARQL. If a SPARQL query is used as the definition of a view then that view can be manipulated using SQL like any other view. In this way the result set from a SPARQL query can be easily accessed from Visual Studio using ADO.Net and the Entity Framework.
GRANT EXECUTE ON DB.DBA.RDF_MAKE_LONG_OF_SQLVAL TO "demo"
CREATE VIEW Demo.demo.sparqlview AS SPARQL PREFIX nwind: <http://demo.openlinksw.com/schemas/northwind#> SELECT DISTINCT ?s FROM <http://demo.openlinksw.com/Northwind> WHERE { ?s a nwind:Customer }
int column = e.ColumnIndex; object o = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; Type t = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].ValueType; if (o is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString) o; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, this.sparqlviewTableAdapter.Connection); seHandler.displayData(); } else if (o is SqlRdfBox) { //doesn't do anything at the moment }
using OpenLink.Data.Virtuoso;
using OpenLink.Data.Virtuoso; using System.Data; using System.Windows.Forms; using System.Drawing; using System.Data.Mapping; using System.Data.Common;
StringBuilder DescribeCommand; VirtuosoConnection ParentConnection; List<Label> labelList = new List<Label>(); List<TextBox> textBoxList = new List<TextBox>(); DescribeDataSet describeDataSet = new DescribeDataSet(); Boolean isIRI = false; public ExtendedStringHandler(SqlExtendedString iri, VirtuosoConnection parentConnetion) { ParentConnection = parentConnetion; if (iri.IriType == SqlExtendedStringType.IRI) { isIRI = true; DescribeCommand = new StringBuilder("sparql SELECT * FROM <http://demo.openlinksw.com/Northwind> WHERE {<" + iri.ToString() + "> ?p ?o}"); // Replace demo.openlinksw.com in line above with your URIQA DefaultHost setting } } public string describeCommandText { get { return DescribeCommand.ToString(); } } public void getDescribeData() { VirtuosoCommand myCommand = new VirtuosoCommand(this.describeCommandText, this.ParentConnection); VirtuosoDataAdapter myAdapter = new VirtuosoDataAdapter(); myAdapter.SelectCommand = myCommand; myAdapter.Fill(describeDataSet.DataTable1); } public void displayData() { if (isIRI) { getDescribeData(); Form describeForm = new Form(); describeForm.AutoScroll = true; describeForm.Width = 840; Label label1 = new Label(); label1.AutoSize = true; label1.Font = new Font(label1.Font.FontFamily, label1.Font.Size + 3.0F, label1.Font.Style | FontStyle.Bold, label1.Font.Unit); describeForm.Controls.Add(label1); DataTable table1 = describeDataSet.Tables[0]; if (table1.Rows.Count == 0) label1.Text = "No Details Available"; else { foreach (DataRow row in table1.Rows) if (row[0].ToString() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { StringBuilder title = new StringBuilder(row[1].ToString() + " details"); label1.Text = title.ToString(); break; } foreach (DataRow row in table1.Rows) { Label propertyLabel = new Label(); TextBox valueBox = new TextBox(); valueBox.Width = 400; object property = row[0]; object value = row[1]; if (value is SqlExtendedString) { valueBox.ForeColor = Color.Blue; valueBox.Font = new Font(valueBox.Font.FontFamily, valueBox.Font.Size, valueBox.Font.Style | FontStyle.Underline, valueBox.Font.Unit); } propertyLabel.Text = row[0].ToString(); propertyLabel.AutoEllipsis = true; propertyLabel.AutoSize = false; propertyLabel.Width = propertyLabel.PreferredWidth > 380 ? 380 : propertyLabel.PreferredWidth; Binding bind = new Binding("Text", row[1], ""); valueBox.DataBindings.Add(bind); labelList.Add(propertyLabel); textBoxList.Add(valueBox); } for (int i = 0; i < table1.Rows.Count; i++) { textBoxList[i].Click += new EventHandler(this.iri_Click); labelList[i].Location = new Point(10, i * 20 + 50); textBoxList[i].Location = new Point(400, i * 20 + 50); describeForm.Controls.Add(labelList[i]); describeForm.Controls.Add(textBoxList[i]); } describeForm.Height = labelList.Count * 20 + 100 > 500 ? 500 : labelList.Count * 20 + 100; } describeForm.ShowDialog(); } else { Form blankForm = new Form(); Label label1 = new Label(); label1.Text = "Blank Node"; label1.Font = new Font(label1.Font.FontFamily, label1.Font.Size + 3.0F, label1.Font.Style | FontStyle.Bold, label1.Font.Unit); blankForm.ShowDialog(); } } public void iri_Click(object sender, EventArgs e) { int boxNum = 0; for (int i = 0; i < textBoxList.Count; i++) { if (sender == textBoxList[i]) { boxNum = i; break; } } Object o = describeDataSet.DataTable1.Rows[boxNum][1]; if (o is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString)o; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, ParentConnection); seHandler.displayData(); } else if (o is SqlRdfBox) { //doesn't do anything at the moment } }
You will notice if you keep clicking on the links that this application will only display data that is held in the Northwind graph. Clicking on an external link, for example the link to Berlin in dbpedia, http://dbpedia.org/resource/Berlin, results in a empty window and an error message. The next step is to extend this application so that it can handle dereferencing external IRIs.