繁体   English   中英

Dapper 使用存储过程返回插入的值

[英]Dapper return inserted value using stored procedures

我有一个 class 从 SQL 服务器插入和加载任何 model:

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);
    }
}

它们都是调用存储过程的函数,例如:

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

它使用下表:

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

要插入作者,我使用以下 function:

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

现在我需要进行更改,以便当我插入作者时它返回带有 id 的寄存器,我尝试更改QueryFirstAsync但它不会返回 model。 我可以改变什么来使这个通用的 function 返回保存的寄存器?

另外附带说明一下, LoadData function 是否可以传递多个模型,以便在使用具有以下连接的存储过程时可以拆分它们:

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

一个简单的获取示例:

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;
}

(因为您的“spAuthors_Insert”是基于单行的(而不是基于集合),您可以执行以下操作)。

您的存储过程需要执行 SELECT。 (作为它的最后一条指令)。 使用以下三个“身份”功能之一的 select。

以下三个之一:(可能按优先顺序,请参阅: Scope_Identity()、Identity()、@@Identity 和 Ident_Current() 之间有什么区别?

SELECT SCOPE_IDENTITY()

或者

SELECT IDENT_CURRENT('tablename')

或者

SELECT @@IDENTITY

(您的表名是“作者”)

..

然后你的 ExecuteAsync

可能需要

https://docs.microsoft.com/en-us/dotnet/api/system.data.common.dbcommand.executescalarasync?view=net-6.0

ExecuteScalar(异步)

因为您需要获取该单列/行值。

从文档中:

ExecuteScalar() 的异步版本,它执行命令并返回第一个返回结果集中第一行的第一列。 所有其他列、行和结果集都将被忽略。

注意“第一行的第一列”。 (也不要错过“第一个返回的结果集”)。

(又名,确保存储过程中唯一的“选择”是上述三个 IDENTITY 函数之一。

并在 c# 代码上“点 i”。

Task SaveData<T>(

我会改为:

Task<long> SaveSingle<T>(

或者可能

Task<K> SaveSingle<T,K>(

(以上是本意,方法上的generics定义我还没试过。

其中 K 是“int”或“long”(ms-sql-server 中的 INT、BIGINT)......并且您返回新的 PrimaryKey。

并将.ExecuteScalarAsync的结果转换为long或K。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM