Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6672429
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T03:30:26+00:00 2026-05-26T03:30:26+00:00

Our legacy web application heavily uses stored procedures. We have a central interface through

  • 0

Our legacy web application heavily uses stored procedures. We have a central interface through which all database calls (i.e. queries and procedures) are made. However, the current implementation uses the OracleCommandBuilder.DeriveParameters method under the hood to bind to the appropriate stored procedure signature. From the documentation:

DeriveParameters incurs a database round-trip and should only be used during design time.
To avoid unnecessary database round-trips in a production environment, the
DeriveParameters method itself should be replaced with the explicit parameter settings
that were returned by the DeriveParameters method at design time.

We could use the OracleCommand class to explicitly bind to the correct stored procedure signature. However, littering our code (even if only the Data Access Layer) with OracleCommand objects is not database agnostic. We already support database agnostic dynamic queries in our database interface (hereafter referred to as IDatabaseService), which looks like this:

int ExecuteNonQuery(string query, object[] parameterValues);
IDataReader ExecuteReader(string query, object[] parameterValues);
// etc.

We want to also support database agnostic stored procedure calls. What is a good pattern for this?

More information:

To bind to a specific subroutine, OracleCommands allow BindByName. We prefer to not use that approach, as a string is more error-prone than a type. The other approach for binding a subroutine call is to provide the parameter types. We could rely on the parameter values and reflect on the runtime types, but we want stronger safety than that. We want to require that the types are explicitly provided to the database interface so that we can check that the provided parameter values match the provided subroutine parameter types before we communicate to the database.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T03:30:27+00:00Added an answer on May 26, 2026 at 3:30 am

    After prototyping various approaches, we settled on the following.

    To IDatabaseService we added new ExecuteYYY methods that take an object implementing IDatabaseSubroutineSignature and (optionally, via an overload) an IEnumerable that are the parameter values.

    The ExecuteYYY methods on IDatabaseService look like this:

    DataSet ExecuteDataSet(IDatabaseSubroutineSignature signature);
    DataSet ExecuteDataSet(IDatabaseSubroutineSignature signature, IEnumerable<object> parameterValues);
    void ExecuteNonQuery(IDatabaseSubroutineSignature signature);
    void ExecuteNonQuery(IDatabaseSubroutineSignature signature, IEnumerable<object> parameterValues);
    IDataReader ExecuteReader(IDatabaseSubroutineSignature signature);
    IDataReader ExecuteReader(IDatabaseSubroutineSignature signature, IEnumerable<object> parameterValues);
    object ExecuteScalar(IDatabaseSubroutineSignature signature);
    object ExecuteScalar(IDatabaseSubroutineSignature signature, IEnumerable<object> parameterValues);
    ReadOnlyCollection<object> ExecuteScalarMultiple(IDatabaseSubroutineSignature signature);
    ReadOnlyCollection<object> ExecuteScalarMultiple(IDatabaseSubroutineSignature signature, IEnumerable<object> parameterValues);
    

    There are some differences between the standard .NET BCL ExecuteYYY methods and the above:

    • Our ExecuteNonQuery methods return void. This is because ExecuteNonQuery (on the command object) always returns -1 when a stored procedure is executed.
    • We have introduced a new ExecuteScalarMultiple method. This accounts for multiple output parameters.

    IDatabaseSubroutineSignature looks like this:

    public interface IDatabaseSubroutineSignature
    {
        string Name { get; }
        IEnumerable<IDatabaseSubroutineParameter> Parameters { get; }
    }
    
    public interface IDatabaseSubroutineParameter
    {
        ParameterType Type { get; }
        ParameterDirection Direction { get; }
    }
    
    // Using custom DbType attribute.
    public enum ParameterType
    {
        [DbType(DbType.Decimal)]
        Decimal,
        [DbType(DbType.String)]
        String,
        [DbType(DbType.StringFixedLength)]
        Character,
        RefCursor,
        [DbType(DbType.Double)]
        Double,
        [DbType(DbType.Int32)]
        Int32,
        [DbType(DbType.Int64)]
        Int64,
        [DbType(DbType.DateTime)]
        DateTime
    }
    

    The final problem we had is with a convenient way to create (and represent) the signatures in code. We settled on a monadesque approach by creating a subinterface of IDatabaseSubroutineSignature that exposes methods for creating parameters:

    public interface IDatabaseSubroutineSignatureCreator : IDatabaseSubroutineSignature
    {
        IDatabaseSubroutineSignatureCreator Input(ParameterType dbType);
        IDatabaseSubroutineSignatureCreator Output(ParameterType dbType);
        IDatabaseSubroutineSignatureCreator InputOutput(ParameterType dbType);
        IDatabaseSubroutineSignatureCreator ReturnValue(ParameterType dbType);
    }
    

    Finally, here is a usage example:

    private static readonly IDatabaseSubroutineSignature MyProcedureSignature =
        DatabaseSubroutineSignatureFactory.Create("pkg.myprocedure")
            .Input(ParameterType.Decimal)
            .Input(ParameterType.String)
            .Output(ParameterType.RefCursor);
    
    public IEnumerable<DataObject> CallMyProcedure(decimal userId, string searchQuery)
    {
        using (IDatabaseService dbService = ...)
        using (IDataReader dataReader = dbService.ExecuteReader(MyProcedureSignature,
            new object[] { userId, searchQuery }))
        {
            while (dataReader.Read())
            {
                yield return new DataObject(
                    dataReader.GetDecimal(0),
                    dataReader.GetString(1));
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a legacy application in our company built on... ahem; Classic VB (VB
The legacy web app I have inherited, which was custom-written for Oxfam New Zealand
We have a legacy VB6 application which has worked just fine on Windows XP
In our legacy Java EE application, there are loads of value object (VO) classes
I am refactoring a part of our legacy app which handles exporting and importing
I've encountered an interesting problem while developing for our legacy XWindows application. For reasons
I’m looking at rewriting a portion of our application in C# (currently legacy VB6
All custom legacy software needs changing, or so say our users. Sometimes they want
So I've got our legacy app which is classic asp and I've got a
We deployed our legacy ASP.NET application to production after successful test deployments to our

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.