Visiting SQL - Part 2

In part 1 I explained how I got a "typed model" of a database schema for building SQL in code. By itself I found this useful, but I still hated the string concatenation involved (not to speak of the scattering of all this string manipulation). So I came up with the idea to build a hand-made object model for all SQL query related objects. This model would allow me to build SQL statements in a typed and database-agnostic fashion, integrating nicely with my typed database schema model. To give you a rough idea I included some schematics:

- The core interfaces -

- The core classes (and some derived ones to give you an idea) -


The main interfaces of interest are ISqlSerializable (a.k.a. IVisitable with the accept method replaced with the more appropriate WriteSql) and ISqlWriter (a.k.a. the Visitor). Basically, I've taken the visitor pattern and applied it to writing SQL, allowing for extensibility (
for each of the SQL dialects out there) and refraining developers (in theory) from polluting the code with string concatenated SQL. The not so apparent added value is the amount of reuse one can achieve with this type of model (from caching to creating dynamic views).
The only drawback (maybe there are more, but this is the major one) to using an object model is that your SQL becomes very much unreadable as complexity grows. Then again, this may be a sign that you're not doing enough in your domain model or (e.g. for performance, security reasons) it might be wise to push this logic into a stored procedure. But even this can be solved, by simply modelling each query statement as a class, which can be easily serialized into SQL to see if you get the desired SQL statement (the truly brave might even parse a SQL string and reverse engineer it into the object model).
I think there's enough food for thought in here. Sorry if I haven't gone into too much detail, but a high-level overview is what I had in mind. Feel free to inquire for more.
Published 12 April 2005 11:02 PM by yreynhout

Comments

# Eric Newton said on 13 April, 2005 02:16 PM
its an interesting idea, and obviously not a new one.

any sql object model i've seen breaks down with subqueries :-)

select (select count(*) from orders where orderid=q.orderid) as CountOfOrders,
(select count(*) from qdetails where qid=q.qid) as CountOfItems
from q
# Eric Newton said on 13 April, 2005 02:19 PM
whoops, hit submit too fast.

but i do like the idea of your object model, and the ISqlWriter.

Remember to force your providers to "know" the parameter prefix (@ for sql, : for oracle) and to not introduce the parameter prefix into the parameter name, for true db agnostic

any chance of publishing the code up somewhere?
# Yves Reynhout said on 14 April, 2005 05:04 AM
1. The object model can handle subqueries of that flavor graciously by introducing a SqlQueryExpression which takes a SqlQueryStatement and an alias as it's parameters.
2. ISqlDialect keeps the query writer from having to know the actual parameter symbol(Only necessary if you want to write RAW queries). The symbol injection is delayed until the "visitation".
3. Yes, it's a nice idea for an open source project. I'll think about it.
# Kent Webb said on 14 April, 2005 06:16 PM
Today my team was talking about our difficulties with keeping SQL Stored Procs in sync with various version of DAL code and database schema it rapidly changing environments. Our corporate standard is that SPs must be used for all data access. I was thinking about an approach were the DAL code would know enough to generate it's own SPs. The idea was to add a method to each class that would be called by a utility, generate the matching SP, and allow the DBAs to put into DB.
Can you see where your technique would be of help? Upon ititial read, I was thinking that it could provide the means to ensure that the SP being requested by the DAL actually matched the target DB schema instance. Am I connecting the dots here or not?
# Yves Reynhout said on 14 April, 2005 06:49 PM
Various thoughts:
- Dynamically generating Stored Procedures is something I have thought a lot about myself, because coming up with good names for them can be a very difficult job. The question you should ask yourself is why it is corporate policy to use SPROCs? Changes are reasons of security are at its base. I don't think DBAs are going to be happy about dynamically generated SPROCs. But then again you're probably refering to SPROCs with fixed names.
- Describing all your SPROCs this way (which would include much more than the object model I've presented here (if you want support for IF..THEN, CURSOR, ...)) could make them unmaintainable in the DAL layer. Ofcourse, if these SPROCs are only meant to be wrappers around simple selects, inserts, deletes and updates than it may very well be maintainable.
- Wouldn't it be simpler if you could assert that a given DAL is compatible with a given set of SPROCs, and if you could assert a given set of SPROCs is compatible with a database schema?
Q1 would require your SPROCs to be "master", and your DAL to be generated from the SPROCs("slave"). Making the invocation of your SPROCs typed (each SPROC is a class or a method along with each parameter), would allow the compiler to tell you if the DAL was still compatible with the SPROCs (since the DAL's typed SPROCs are generated, any change will break the code that calls the typed SPROCs).
Q2 could perhaps be solved using checksums for the SPROC text, and matching that up to a database schema version.
- Isn't this a deployment issue: Matching the right set of SPROCs with the right version of the DAL and database schema? Couldn't a decent version control system and unit tests help out here? Isn't this more of a database versioning thing?

Not sure what the best solution is here.
# Victor said on 14 April, 2005 07:48 PM
I'm impressed - very slick model! Like Eric, I'd love to see the source on this one. It seems like your RelationalSchema objects are a nice lean DAL to the database and this model is a low-level querying mechanism for these objects. Now if you add a little facade and reflection you'd be pretty close to a flexible and powerful O/R mapping tool.
# Yves Reynhout said on 15 April, 2005 03:49 AM
This IS part of my object relational mapping code.
# max said on 13 November, 2008 09:26 AM

hello !

I think it's a good idea, and i am interesting in my studies to see your image called "coreclasses.gif" in this part ...

but the image are not visible! the link is dead maybe :) !

Good luck, bye :) !

Leave a Comment

(required) 
(required) 
(optional)
(required)