Lou said:
What I'm after here is a way to store a location for a data source or
sink. I want to keep a uniform link for ANY source or sink. Why should
there be a way to connect to a web site/FTP/Mail/File etc and not have a
way to use that same Uri (emphasis on Universal) without someway of
including SQL in the mix?
Well, one obvious mismatch is that an SQL source produces typed, tabular
data (possibly with multiple result sets), while any sort of file URI
provides an arbitrary byte stream. You need to reconcile those somehow, with
a restriction on the formats produced by either.
The second problem is that it's one thing to allow arbitrary *files*, and
quote another to allow arbitrary *queries* (or even just tables). The latter
may unduly tax the database and/or be disallowed by your DBA, even. If you
mix in parameters, you need a good way to supply those without opening up
SQL injection holes.
Third, while you mention "source or sink", sinks are really very different
animals from sources as far as URIs are concerned. It's very
protocol-dependent what to do with URIs intended to "sink" data: for HTTP
it'll be an HTTP verb (POST or possibly PUT), for FTP it's a PUT command
(but quite unlike HTTP), for mailto: there is actually no source (they're
all "sink" URIs), for file: URIs there is no (standardized) way at all to
create rather than read files. SQL, finally, would have obvious sources
(queries) but not so obvious sinks (a table, yes, but you need to have the
columns and types mapped out in advance). So don't go generalizing just yet!
I'm prepared to 'roll my own' on this. It's an internal thing. I suppose
since most SQL server access is managed intermurrally having a URI wouldn't
provide universal access but I'm looking for consistency of declaration.
Otherwise I'd have to check to see if the string was a connection string or a
URI. Not so terrible I guess but not quite esthetic.
System.Uri provides support for arbitrary schemes, so something like this
will work:
new Uri("mssql://myserver/bookBase/books")
or (with more creativity)
new Uri("mssql://myserver/bookBase/books/{title,isbn}")
to produce arbitrary tuples or heck, go all out with your own language
new
Uri("mssql://myserver/bookBase/books(book),authors(author)/{book.title,
author.name(author)}?book.author=author.id");
That's "SELECT book.title, author.name AS author FROM books book, authors
author WHERE book.author = author.id", can't you tell? I'll leave figuring
out a syntax for outer joins as an exercise...
Since you have to do your own parsing, this is quite a lot of work.
Arbitrary query strings are easier, but you still have issues of escaping to
contend with:
new Uri("mssql://myserver/bookBase?SELECT [title] + '?' FROM books");
This URI is actually
sql://myserver/bookBase?SELECT%20%5Btitle%5D%20+%20'?'%20FROM%20books
And you may have to supply it this way externally, or in an even more
obfuscated form, depending on where you store it. Not obvious or convenient.
Now, instead of *all this*, you could also expose your SQL data as a web
service and consume it as any other HTTP source producing XML. There are so
many ways of doing that that it's not funny: SQL Server can even do this
itself (see, for instance,
http://msdn.microsoft.com/library/ms345123), but
a more scalable solution is to use an IIS web service. ADO.NET Data Services
which I mentioned before are yet another option. A WCF service spitting out
XML using SQL Server's FOR XML options is another. If XML is not your thing,
a simple HTTP handler which returns CSV (or sexy JSON) from a DataReader is
absolutely trivial to build.
Any of these solutions are almost certainly superior (in the sense of
maintainability, scalability and being future-proof) to rolling your own SQL
URI implementations. Whatever works for you, though.