【问题标题】:Alternative way to get output parameter from stored procedure从存储过程获取输出参数的替代方法
【发布时间】:2015-04-23 13:10:42
【问题描述】:

我喜欢使用 Dapper 来满足我的 ORM 需求,但我知道必须有更好的方法来使用存储过程和强类型列表来插入/更新我的 sql server 数据库。

例如:

我有一堂课歌:

    public class Song
{
    public int Id { get; set; }
    public string title { get; set; }
    public string genre { get; set; }
}

有人提交了歌曲列表:

 List<Song> songs = new List<Song> { 
            new Song { Id = 1, title = "Song 1" , genre="rock"}, 
            new Song { Id = 2, title = "Song 2" , genre="disco"}};

我想使用我的存储过程更新数据库,该存储过程要么插入新歌曲,要么在歌曲已经存在时更新它。我的存储过程有两个输出参数: @success_added int = 0 and @success_updated int = 0

我的存储过程如下:

ALTER PROCEDURE [dbo].[UpdateSong] 
@Id int = 0, 
@title varchar(25) = NULL,
@genre varchar(25) = NULL,
@success_updated bit = 0 OUTPUT,
@success_added bit = 0 OUTPUT
AS
IF NOT EXISTS (SELECT Id  FROM Songs WHERE Id = @Id)
    BEGIN
        INSERT INTO Songs
        (
        -- Id created by db
        title,
        genre
        ) 
        VALUES
        (
        @title, 
        @genre
        )
        SELECT @Success_Added = 1, @Success_Updated = 0
    END
ELSE -- song already exists
    BEGIN
        UPDATE Songs  
        SET
        title = @title,
        @genre = @genre
        WHERE Id = @Id
        SELECT @Success_Added = 0, @Success_Updated = 1
    END
RETURN

我知道这行得通:

dbConn.Open();
DynamicParameters p = new DynamicParameters();
foreach (var song in songs)
  {
    p.Add("@Id", song.Id);
    p.Add("@title", song.title);
    p.Add("@genre", song.genre);
    p.Add("@success_updated", dbType: DbType.Boolean, direction: ParameterDirection.Output);
    p.Add("@success_added", dbType: DbType.Boolean, direction: ParameterDirection.Output);
    dbConn.Execute("Test_UpdateSong", p, commandType: CommandType.StoredProcedure);
    Console.WriteLine("@success_added: " + p.Get<Boolean>("@success_added"));
    Console.WriteLine("@success_updated: " + p.Get<Boolean>("@success_updated"));
  }
dbConn.Close();

但这需要手动将每个 Song 属性转换为匿名类型 DynamicParameter。我宁愿简单地这样做:

dbConn.Open();
foreach (var song in songs)
  {
    var updateResult = dbConn.Query<dynamic>("Test_UpdateSong", song, commandType: CommandType.StoredProcedure);
  }
dbConn.Close();

这也有效。但是,现在我如何获取我的输出参数?

【问题讨论】:

  • 存储过程返回数据至少有4种方式:记录集、返回参数、输出参数、打印、raiserror。代码中的 Query 对象返回什么?记录集?您可以更改您的 SP 以在包含多列的单行中返回结果
  • 也许如果您发布现有的 SP 代码,它可能会进一步启发事情
  • @尼克。 McDermaid,我添加了上面的 sproc 以供审查。 Query 就在那里,因为 Execute 方法在不显式添加动态参数的情况下不会返回任何内容。谢谢。
  • 如果您还没有这样做,请查看 dapper 测试类; dapper 支持的每个排列都有一个支持单元测试:github.com/StackExchange/dapper-dot-net/blob/master/Tests/…
  • 如果您将SELECT @success_updated AS success_updated, @success_added AS success_added 添加到您的SP 的末尾(就在return 之前),您是否在查询对象的输出中看到它? (只是在这里猜测。我不知道 Dapper 是什么)

标签: dapper


【解决方案1】:

正如我最初所说,我不想手动将每个类属性转换为 Dapper 动态参数。这很关键,因为如果我创建一个泛型方法,我可能不知道哪个类被传递到该方法中,因此不知道要传递哪些属性以转换为动态参数。接受@Metro Smurfs 的建议(当所有其他方法都失败时,请阅读说明),我查看了 Dapper 测试类并找到了一个适合我的解决方案:

DynamicParameters p = new DynamicParameters(song);

通过将歌曲对象添加到 DynamicParameters 构造函数,将创建一个 DynamicParameters 模板,该模板将自动将所有属性转换为参数。然后我可以简单地添加我的两个输出参数并执行存储过程:

p.Add("@success_updated", dbType: DbType.Boolean, direction: ParameterDirection.Output);
p.Add("@success_added", dbType: DbType.Boolean, direction: ParameterDirection.Output);
dbConn.Execute("Test_UpdateSong", p, commandType: CommandType.StoredProcedure);
// get my output parameters...
var success_added = p.Get<bool>("@success_Added");
var success_added = p.Get<bool>("@success_Updated");

我可以走了!感谢@Nick 和@Metro Smurf 的建议!

【讨论】:

  • 这很好 - 但我不需要参数名称前面的@。
  • 我尝试了这种方法,但是当您的实体具有一个更复杂的属性时不起作用
猜你喜欢
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 2019-02-03
  • 1970-01-01
相关资源
最近更新 更多