Sparql connection issues

Apr 1, 2014 at 9:21 AM
BrightstarEntityContext needs some changes in order to work with a sparql connection string:
  • add case ConnectionType.Sparql:
private static IDataObjectStore OpenStore(ConnectionString connectionString, bool? enableOptimisticLocking = null,
            string updateGraphUri = null, IEnumerable<string> datasetGraphUris = null, string versionGraphUri = null)
        {
            IDataObjectContext context;
            switch (connectionString.Type)
            {
....................
                case ConnectionType.DotNetRdf:
                case ConnectionType.Sparql:
                    context = BrightstarService.GetDataObjectContext(connectionString);
                    //context = new DotNetRdfDataObjectContext(connectionString);
                    break;
also add here:
 private static void AssertStoreFromConnectionString(ConnectionString connectionString)
        {
            if (connectionString.Type == ConnectionType.DotNetRdf || connectionString.Type == ConnectionType.Sparql)
            {
                return;
            }
And
storeName.Equals(_storeName)) translates at runtime into:
null = "sparql" so I commented the check
public IDataObjectStore OpenStore(string storeName, Dictionary<string, string> namespaceMappings = null, bool? optimisticLockingEnabled = null,
                                          string updateGraph = null, IEnumerable<string> defaultDataSet = null,
                                          string versionTrackingGraph = null)
        {
            //if (!storeName.Equals(_storeName)) throw new BrightstarClientException(Strings.BrightstarServiceClient_StoreDoesNotExist);
            return new SparqlDataObjectStore(QueryProcessor, UpdateProcessor, namespaceMappings,
                                             optimisticLockingEnabled.HasValue
                                                 ? optimisticLockingEnabled.Value
                                                 : OptimisticLockingEnabled,
                                             updateGraph, defaultDataSet, versionTrackingGraph);
        }
Coordinator
Apr 1, 2014 at 3:52 PM
Fix pushed to develop. Rather than remove the store name check I've just changed the connection string parser so that a SPARQL connection string always gets a default store name of "sparql", so the null exception won't happen now.
Apr 3, 2014 at 8:42 AM
When connecting using sparql endpoints depending of provider I need more control on the actual connection.
For example when an Ask query is sent to Virtuoso by default dnr creates a http request with header that has Accept: text/plain, text/rdf, text/turtle.... and 20 more but in this case Virtuoso returns a json response with content type text/plain so dnr fails at parsing.
If instead accept: * / * then it returns text/turtle and dnr parses it.
So I added a constructor to context:
  /// <summary>
        /// Creates a new domain context and connects to the store using queryProcessor/updateProcessor.
        /// </summary>
        /// <param name="mappings"></param>
        /// <param name="versionGraphUri"></param>
        /// <param name="queryProcessor"></param>
        /// <param name="updateProcessor"></param>
        /// <param name="updateGraphUri"></param>
        /// <param name="datasetGraphUris"></param>
        protected BrightstarEntityContext(
            EntityMappingStore mappings,
            ISparqlQueryProcessor queryProcessor,
            ISparqlUpdateProcessor updateProcessor,
            string updateGraphUri = null,
            IEnumerable<string> datasetGraphUris = null, 
            string versionGraphUri = null)
            : base(mappings)
        {
            var cstr = new ConnectionString(Configuration.ConnectionString);
            IDataObjectContext context = new SparqlDataObjectContext(queryProcessor, updateProcessor, cstr.OptimisticLocking);
            _store = new SparqlDataObjectStore(
                queryProcessor, 
                updateProcessor, 
                namespaceMappings:null,
                optimisticLockingEnabled:false,
                updateGraphUri: updateGraphUri,
                datasetGraphUris: datasetGraphUris,
                versionGraphUri: versionGraphUri);
                
            _trackedObjects = new Dictionary<string, List<BrightstarEntityObject>>();
        }
so now I can pass the dnr processors from outside.

I also created a partial class to keep reference to processors:
public partial class MyEntityContext
    {
        public ISparqlQueryProcessor QueryProcessor { get; set; }
        public ISparqlUpdateProcessor UpdateProcessor { get; set; }

        public MyEntityContext(
          ISparqlQueryProcessor queryProcessor,
          ISparqlUpdateProcessor updateProcessor,
          string updateGraphUri = null,
          IEnumerable<string> datasetGraphUris = null,
          string versionGraphUri = null)
            : base(TypeMappings, queryProcessor, updateProcessor, updateGraphUri, datasetGraphUris, versionGraphUri)
        {
            InitializeContext();
            UpdateProcessor = updateProcessor;
            QueryProcessor = queryProcessor;
        }
    }
This was necessary because the B* context only has an .ExecuteQuery() (that is parsed as sparql), but I don't know how I can do an update, so maybe an ExecuteUpdate method should be added for people that don't use sparql endpoint.
Coordinator
Apr 3, 2014 at 8:04 PM
You can pass in DNR processors like this:
            var queryProcessor = new MySparqlQueryProcessor();
            var updateProcessor = new MySparqlUpdateProcessor();
            var doContext = new SparqlDataObjectContext(queryProcessor, updateProcessor, false);
            var store = doContext.OpenStore("sparql");
            var context = new MyEntityContext(store);
You build the SparqlDataObjectContext first, then use that to open the specially named "sparql" store and pass that in when creating the EF context. I think you maybe couldn't get this approach to work before because I hadn't documented that "sparql" is the magic string for getting the store when connecting to a SPARQL endpoint. I think this is enough for your purposes though and I want to avoid complicating the API with more constructors if I can! Let me know if there is a reason why the above wouldn't work for you though.

If you want to execute updates separately from EF, just execute them using the update processor. But then be sure to create your context again when you want to use EF to avoid any issues with internally cached triples.