I am attempting to create a stored procedure/ADO.NET mapping mechanism where a stored procedure with parameters becomes
object MyStoredProcedure.Execute(out returnValue, param1, param2, ...)
The problem comes when trying to generate the actual data retrieval method. I can easily obtain most of the schema information I need from the Information Schema views, but I can’t reliably find what type of return (output param vs. SELECT/SqlDataReader vs. both) should come from the procedure and whether to call ExecuteNonQuery or ExecuteReader.
Worst-case, I can probably parse the procedure’s text, but there are all kinds of funky things that could go wrong there.
The reason for the code generation is that the application database contains many hundreds of stored procedures. And we inherited this project, so there is no way to wrap our heads around that many procs that we didn’t create.
I actually have two main goals for the ADO.NET generation:
1) Remove all string literals (stored proc names in SqlCommand creation, parameter names in SqlParameter creation, etc.) from the application. This way, when a procedure or database schema changes, we can regenerate the ADO.NET wrappers, and any errors resulting from those changes will be caught at compile time.
2) Remove the need to dig through a proc to determine params, returns types, etc. So basically, the database itself becomes an API, with all of the internal stored procedure details abstracted away.
Yup; that isn’t easy. For simple cases you can try running the sp (awooga!) passing nulls for all the parameters, and using
SET FMTONLY ON– a bit risky (extended sprocs are stll executed, for example) and not robust since the TSQL could branch on the input. But an option.The “out” ets should be available via metadata; the “old” way would be
syscolumns(there is probably an info-schema alternative for doing it the right way).Just as an update; if you want the database to describe itself as an API, perhaps consider UDFs for the selects; advantages:
Or; just use an ORM. LINQ-to-SQL will work happily with this type of setup (including composability); Entity Framework will certainly do all that hard work for you for stored procedures. Or any of the others; NHibernate, LLBLGen Pro, etc. They have all tackled this exact problem. It isn’t trivial; why re-invent it?