簡體   English   中英

使用存儲過程從 Dapper.net 查詢返回值

[英]Return Values from Dapper.net query with stored procedure

我正在嘗試using Dapper.Net調用存儲過程並獲取返回值。

p.Add("@INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);

int IncidentID = p.Get<int>("INCIDENT_ID"); 

我在參數方向和使用"@INCIDENT_ID"方面嘗試了幾種不同的方法。 如果您逐步查看結果,您可以看到正確的返回值在retResults值中下降,但我無法按照文檔中描述的方式訪問這些值,如下所示。

存儲過程 Dapper 支持完全存儲過程:

var user = cnn.Query<User>("spGetUser", new {Id = 1}, 
    commandType: CommandType.StoredProcedure).First();}}}
If you want something more fancy, you can do:

var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

cnn.Execute("spMagicProc", p, commandType: commandType.StoredProcedure); 

int b = p.Get<int>("@b");
int c = p.Get<int>("@c");   

懷疑(未經測試)這純粹是您命名參數的方式不匹配; 嘗試(注意刪除的@ ):

p.Add("INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);

int IncidentID = p.Get<int>("INCIDENT_ID"); 

您可以讀取如下值

var incidentId = retResults.ToList()[0].INCIDENT_ID; 

使用 Dapper 的測試版本,我發現這很有效:

result = dbConnection.ExecuteScalar<int>(typeof(UCCCCException).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);

我正在編寫一個泛型,用於將任何類型的對象插入到數據庫中。

存儲過程如下所示:

ALTER PROCEDURE [dbo].[UCCCCException_c]
(
@Id int = null,
@ExceptionDate datetime = null,
@HResult int = 0,
@Message varchar(8000) = null,
@Source varchar(8000) = null,
@StackTrace varchar(8000) = null,
@Module varchar(8000) = null,
@Name varchar(8000) = null,
@created_at datetime = null,
@updated_at datetime = null,
@created_by int = null,
@updated_by int = null
,
@Creator varchar(255) = null,
@Updator varchar(255) = null
)
AS

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

Insert into dbo.uccccexceptions ( ExceptionDate, HResult, [Message], [Source], StackTrace, Module, Name)
                            values (
                                    coalesce(@ExceptionDate,getdate()),
                                    @HResult,
                                    @Message,
                                    @Source,
                                    @StackTrace,
                                    @Module,
                                    @Name
                                    )
                                    ;
select @@Identity;
go

對此的警告是,您必須為正在使用的類中的每個屬性指定一個條目作為存儲過程的參數,即使這些屬性不存在於目標表中。 如果您有許多字段是 MVC 情況下的視圖字段,這可能會很煩人。

要獲取返回值,您只需使用 Execute,並確保您的最后一條語句是存儲過程中的 Select @@Identity。

它工作得很好,並允許我在我的存儲庫中編寫一個通用的插入命令,如下所示:

        public virtual int Insert(T obj)
    {
        int result = -2;
        if (!databaseOnline)
        {
            throw new Exception(HttpStatusCode.ServiceUnavailable.ToString());
        }
        if (obj != null)
        {
            try
            {
                using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
                {
                    dbConnection.Open();
                    result = dbConnection.ExecuteScalar<int>(typeof(T).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);
                }
            }
            catch (SqlException sqlex)
            {
                Logger.LogError(sqlex, false);
                throw;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }
        }
        return result;
    }

我在我的數據庫中使用約定,存儲過程的名稱是類型名稱后跟“_s”表示選擇,“_c”表示插入,“_d”表示刪除,“_u”表示更新。

PS:我討厭使用 Dapper 的 DynamicParameters 或任何其他要求您對通用存儲庫中的每個類使用不同的插入或更新方法的設備。

我在讀取 QueryMultiple 的結果時遇到了類似的問題。 第一次調用 Read() 返回正確的類型,第二次調用返回 DapperRow。 我發現使用 Read() 的類型化版本:

var lineExists = query.Read<int?>().FirstOrDefault() == 1;

解決了我的問題。

為簡單起見,我已經縮減了這一點。 我正在使用輸出參數,因為這使我可以完全控制傳回的數據類型。 我可以將這種方法用於任何其他場景,而不僅僅是插入。

存儲過程:

ALTER PROCEDURE User_Insert (
@EmailAddress nvarchar(255),
@Id bigint OUT
) AS
INSERT INTO User (
        [EmailAddress]
    ) VALUES (
        @EmailAddress
    )
    set @Id = SCOPE_IDENTITY()

存儲庫代碼:

var sql = "Execute User_Insert @EmailAddress, @Id = @Id OUTPUT";
var _params = new DynamicParameters();
_params.Add("EmailAddress", user.EmailAddress);
_params.Add("Id", dbType: DbType.Int64, direction: ParameterDirection.Output);

using (var connection = new SqlConnection(ConnectionString)) {
    connection.Open();
    using (var transaction = connection.BeginTransaction()) {
        var result = SqlMapper.Execute(connection, sql, param, transaction);
        transaction.Commit();
    }
}    
var id = _params.Get<long>("Id");

DynamicParameters 解決方案對我來說並不干凈。 最好讓存儲過程代碼返回一個整數 (Select 1;) 並使用 dapper ExecuteScalar<int>("[sp_name]", params);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM