Core Concepts > Stored Procedures

Executing Stored Procedures

To return data from execution of a stored procedure, dbExpression uses various methods in the fluent method chain just before Execute and ExecuteAsync. Use one of these methods to end the stored procedure query and specify the return:

GetValue<T>()Execution of the stored procedure returns a scalar value with type T.
GetValues<T>()Execution of the stored procedure returns a list of scalar values with type T.
GetValue<T>(Func<ISqlFieldReader,T>)Execution of the stored procedure returns an object of type T.
GetValues<T>(Func<ISqlFieldReader,T>)Execution of the stored procedure returns a list of objects with type T.
GetValue()Execution of the stored procedure returns a single dynamic object, where the properties of the dynamic object are determined by the returned rowset.
GetValues()Execution of the stored procedure returns a list of dynamic objects, where the properties of each dynamic object are determined by the returned rowset(s).

Returning a scalar value

To return a scalar value from execution of a stored procedure, use the generic GetValue<T> method, where T is the desired return type.
For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetMaxCreditLimitLessThan]
    @CreditLimit INT
AS
    SELECT
        MAX([dbo].[Person].[CreditLimit])
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit
//get the max credit limit for all persons when the credit limit is less than 1,000,000.
int maxCreditLimt = db.sp.dbo.GetMaxCreditLimitLessThan(1000000).GetValue<int>().Execute();

Returning a list of scalar values

To return a list of scalar values from execution of a stored procedure, use the generic GetValues<T> method, where T is the desired return type. Using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetPersonsWithCreditLimitLessThan]
    @CreditLimit INT
AS
    SELECT
        [dbo].[Person].[Id]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit
//get all person ids where the person has a credit limit less than 20000
IEnumerable<int> personIds = db.sp.dbo.GetPersonsWithCreditLimitLessThan(20000).GetValues<int>().Execute();

Returning an object

To return an object from execution of a stored procedure, use the generic GetValue<T> method with a mapping delegate (Func<ISqlFieldReader,T>). The mapping delegate defines the type (T) returned from the method, and the function used to read fields from a row and map to a T. For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetPersonById]
    @Id INT
AS
    SELECT
        [dbo].[Person].[Id],
        [dbo].[Person].[FirstName],
        [dbo].[Person].[LastName]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[Id] = @Id

This stored procedure can be executed with a mapping delegate to read the values from the row and map to an instance of a class of type Person:

Person? person = db.sp.dbo.GetPersonById(1).GetValue(
    row => new Person 
    { 
        Id = row.ReadField()!.GetValue<int>(),
        FirstName = row.ReadField()!.GetValue<string>(),
        LastName = row.ReadField()!.GetValue<string>()
    }).Execute();

Returning a list of objects

To return a list of objects from execution of a stored procedure, use the generic GetValues<T> method with a mapping delegate (Func<ISqlFieldReader,T>). The mapping delegate defines the type (T) returned from the method, and the function used to read fields from a row and map to a T. For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetPersonsWithCreditLimitLessThan]
    @CreditLimit INT
AS
    SELECT
        [dbo].[Person].[Id],
        [dbo].[Person].[FirstName],
        [dbo].[Person].[LastName]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit
IEnumerable<Person> persons = db.sp.dbo.GetPersonById(1).GetValues(
    row => new Person 
    { 
        Id = row.ReadField()!.GetValue<int>(),
        FirstName = row.ReadField()!.GetValue<string>(),
        LastName = row.ReadField()!.GetValue<string>()
    }).Execute();

Returning a dynamic object

To return a dynamic object from execution of a stored procedure, use the GetValue method. For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetMaxCreditLimitLessThan]
    @CreditLimit INT
AS

    SELECT
        MAX([dbo].[Person].[CreditLimit]) AS [MaxCreditLimit],
        COUNT([dbo].[Person].[Id]) AS [PersonCount]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit

Note the aliasing of each field, which is required to successfully create and map data to a dynamic object.

//get all persons where the person has a credit limit less than 20000
IEnumerable<dynamic> persons = db.sp.dbo.GetPersonsWithCreditLimitLessThan(20000).GetValues().Execute();

Returning a list of dynamic objects

To return a list of dynamic objects from execution of a stored procedure, use the GetValues method. For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetPersonsWithCreditLimitLessThan]
    @CreditLimit INT
AS
    SELECT
        [dbo].[Person].[Id],
        [dbo].[Person].[FirstName],
        [dbo].[Person].[LastName]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit
//get all persons where the person has a credit limit less than 20000
IEnumerable<dynamic> persons = db.sp.dbo.GetPersonsWithCreditLimitLessThan(20000).GetValues().Execute();

Execution and Reading Data via a Delegate

Similar to the methods used to return data from a stored procedure, a method is available that expects data to be returned from the target database, but doesn't return data from execution of the method (method return type is void). This method is useful when it is preferable to handle each row as it is read from the target database instead of waiting for the full data set as a return from the method. Example use cases may be when you are working with very large data sets, streaming data directly to a file, publishing to an event sink or posting to a data pipeline. This method has a delegate parameter that is executed as each row is read from the target database. The ISqlFieldReader is just an abstraction over a DataReader. The method has the following signature:

  • MapValues(Action<ISqlFieldReader>) - the stored procedure returns data, but each row read from the target database is passed to the delegate.

For example, using a stored procedure defined as follows:

CREATE PROCEDURE [dbo].[GetPersonsWithCreditLimitLessThan]
    @CreditLimit INT
AS
    SELECT
        [dbo].[Person].[Id],
        [dbo].[Person].[FirstName],
        [dbo].[Person].[LastName]
    FROM
        [dbo].[Person]
    WHERE
        [dbo].[Person].[CreditLimit] < @CreditLimit

While the following code example loads all data into memory similar to the use of GetValues, the purpose is to demonstrate how to use the MapValues method with a delegate to handle each row as it is read from the target database.

var persons = new Dictionary<int,string>();

db.sp.dbo.GetPersonsWithCreditLimitLessThan(20000).MapValues(
    row =>
    {
        var id = row.ReadField()!.GetValue<int>();
        var firstName = row.ReadField()!.GetValue<string>();
        var lastName = row.ReadField()!.GetValue<string>();
        persons.Add(id, $"{firstName} {lastName}");
    }
).Execute();

Execution without Returning Data

For stored procedures that do not return data, omit the "Get..." and "Map..." methods discussed above.

CREATE PROCEDURE [dbo].[SetCreditLimitForPerson]
    @Id INT,
    @CreditLimit INT
AS
    UPDATE
        [dbo].[Person]
    SET
        [dbo].[Person].[CreditLimit] = @CreditLimit
    WHERE
        [dbo].[Person].[Id] = @Id
//update the person with an id of 1 to have a credit limit of 20,000
db.sp.dbo.SetCreditLimitForPerson(1, 20000).Execute();
Previous
Parameters

© 2024 dbExpression. All rights reserved.