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



我有一个从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);
}
}

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

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

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

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

现在我需要进行更改,这样当我插入一个作者时,它会返回带有id的寄存器,我已经尝试为QueryFirstAsync进行更改,但它不会返回模型。我可以更改什么来使这个通用函数返回保存的寄存器?

还有一点需要注意的是,是否可以在LoadData函数上传递多个模型,这样当我使用带有连接的存储过程时,我就可以拆分它们,比如:

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

一个简单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;
}

(因为您的"spAuthors_Insert"是基于单行的(而不是基于设置的(,所以您可以执行以下操作(。

您的存储过程需要执行SELECT。(作为最后一条指令(。使用三个";身份;函数如下。

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

SELECT SCOPE_IDENTITY()

SELECT IDENT_CURRENT('tablename')

SELECT @@IDENTITY

(表名为"作者"(

然后您的ExecuteAsync

可能需要

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

ExecuteScalar(异步(

因为您需要获得单个列/行的值。

来自文件:

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

注意";第一行的第一列";。(并且也不要错过"第一个返回的结果集"(。

(阿卡,确保存储过程中的ONLY"Select"是上面三个IDENTITY函数之一。

而对于";点上i〃;关于c代码。

Task SaveData<T>(

我会换成类似的东西:

Task<long> SaveSingle<T>(

或者

Task<K> SaveSingle<T,K>(

(以上就是我的意图,我还没有尝试过方法上的泛型定义。

其中K是"K";int";或";"长";(ms-sql服务器中的INT、BIGINT(。。。。然后返回新的PrimaryKey。

并将.ExecuteScalerAsync的结果强制转换为long或K.