0
votes

I currently have a class that inserts and loads any model from a SQL Server:

public class SqlDataAccess : ISqlDataAccess
{
    private readonly IConfiguration _configuration;

    public SqlDataAccess(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public async Task<IEnumerable<T>> LoadData<T, U>(string storedProcedure,
                                                     U parameters,
                                                     string connectionId = "Default")
    {
        using IDbConnection connection = new SqlConnection(_configuration.GetConnectionString(connectionId));

        return await connection.QueryAsync<T>(storedProcedure,
                                              parameters,
                                              commandType: CommandType.StoredProcedure);
    }

    public async Task SaveData<T>(string storedProcedure,
                                  T parameters,
                                  string connectionId = "Default")
    {
        using IDbConnection connection = new SqlConnection(_configuration.GetConnectionString(connectionId));

        await connection.ExecuteAsync(storedProcedure,
                                      parameters,
                                      commandType: CommandType.StoredProcedure);
    }
}

They are all functions calling stored procedures, for example:

CREATE PROCEDURE [dbo].[spAuthors_Insert]
    @FirstName NVARCHAR(46),
    @LastName NVARCHAR(46)
AS
BEGIN
    INSERT INTO [dbo].[Authors] (FirstName, LastName)
    VALUES (@FirstName, @LastName);
END

Which uses the following Table:

CREATE TABLE [dbo].[Authors]
(
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,
    [FirstName] NVARCHAR(46),
    [LastName] NVARCHAR(46)
)

To insert an author i use the following function:

public Task InsertAuthor(AuthorModel author) => _db.SaveData("dbo.spAuthors_Insert", new { author.FirstName, author.LastName });

Now I need to change so that when I insert an author it returns the register with the id, I've tried to change for QueryFirstAsync but it doesn't give me the model back, what I can change to make this generic function return the saved register?

Also on a side note, is it possible on the LoadData function pass multiple models so I can split them when I use a Stored Procedure with Joins like:

CREATE PROCEDURE [dbo].[spArts_GetByUserId]
    @Id NVARCHAR(256)
AS
BEGIN
    SELECT *
    FROM [dbo].[Arts]
    INNER JOIN [dbo].[Registrations] ON [dbo].[Arts].id = [dbo].[Registrations].ArtId
    INNER JOIN [dbo].[Arts_details] ON [dbo].[Arts].Arts_details_id = [dbo].[Arts_details].Id
    INNER JOIN [dbo].[Authors] ON [dbo].[Arts_details].AuthorId = [dbo].[Authors].Id
    WHERE UserId = @Id;
END

An example of a simple get:

public async Task<ArtsModel?> GetArt(int id)
    {
        var result_art = await _db.LoadData<ArtsModel, dynamic>("dbo.spArts_Get", new { Id = id });
        var art = result_art.FirstOrDefault();

        return art;
    }