2011-11-04 28 views
3

我目前正在使用的系統使用所有數據訪問的存儲過程。我目前正在研究Dapper(迄今爲止它看起來很棒),但我想知道是否可以使用使用Template創建的DynamicParameters對象,但將其中一個參數設置爲輸出參數。例如:我可以在Template中使用DynamicParameters並在dapper中使用返回參數嗎?

SP:

CREATE PROCEDURE InsertPerson 
    @ID int Output, 
    @Name varchar(100), 
    @DOB DateTime2 
AS 
--INSERT STATEMENT 

SET @ID = SCOPE_IDENTITY() 

POCO:

internal class Person 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public DateTime DOB { get; set; } 
} 

代碼:

var procParams = new DynamicParameters(person); 
connection.Execute("InsertPerson", procParams, commandType: CommandType.StoredProcedure); 

// This is where i'm having the issue, can it be done? 
person.ID = procParams.Get<int>("ID"); 

目前我收到一個錯誤,因爲鍵沒有被發現。有沒有辦法獲得ID輸出參數,而無需手動設置所有存儲的procs參數?

回答

4

一個快速的調整,現在Add替換值從模板,允許:

public void TestProcWithOutParameter() 
{ 
    connection.Execute(
     @"CREATE PROCEDURE #TestProcWithOutParameter 
@ID int output, 
@Foo varchar(100), 
@Bar int 
AS 
SET @ID = @Bar + LEN(@Foo)"); 
    var obj = new 
    { // this could be a Person instance etc 
     ID = 0, 
     Foo = "abc", 
     Bar = 4 
    }; 
    var args = new DynamicParameters(obj); 
    args.Add("ID", 0, direction: ParameterDirection.Output); 
    connection.Execute("#TestProcWithOutParameter", args, 
       commandType: CommandType.StoredProcedure); 
    args.Get<int>("ID").IsEqualTo(7); 
} 

那是足夠接近?您也可以使用ParameterDirection.ReturnValue,既可以是已有值,也可以是新值。請注意,不是直接更新回原始模板;該值必須從DynamicParameters實例中獲取(如圖所示)。

+0

+1爲解釋和項目更新這導致 –

+0

看起來不錯,離開我的筆記本電腦在辦公室週末,但我會檢查星期一。謝謝! – Fermin

+0

@Fermin做到了嗎? –

2

當您使用DynamicParameters的構造函數來指定模板對象時,您仍然需要指定@ID是輸出參數。起初,通過模板,它將被設置爲ParameterDirection.Input。一旦你添加它,它就會被覆蓋有更新的值,那麼你可以通過參數名獲取的價值如下:

procParams.Add("@ID", dbType: DbType.Int32, direction: ParameterDirection.Output); 
// ... execute ... 
person.ID = procParams.Get<int>("@ID"); 

我能得到這個工作,並使用你的類和代碼,在除了我上面展示的內容。

編輯:正如在評論中所討論的那樣,存儲過程不接受比它聲明的更多的參數。因此,另一種方法是放棄存儲過程並使用一些內聯SQL。在使用查詢時,Dapper將忽略在SQL語句中未指定的賦給它的所有參數。這是一個變通來解決這個問題:

string sql = "INSERT INTO Person (Name, DOB) VALUES (@Name, @DOB) SELECT SCOPE_IDENTITY()"; 
decimal id = conn.Query<decimal>(sql, procParams).First(); 
person.ID = (int)id; 

注意SCOPE_IDENTITY()返回小數,而不是一個int。

我認爲不理想的另一個想法是修改Dapper代碼並將Remove方法添加到DynamicParameters類中以刪除不需要的參數。這並不能節省你很多,但是你仍然會花時間指定爲了使存儲過程快樂而刪除所有參數。如果您決定實施此操作,請記住在指定要從parameters字典中刪除的密鑰時該情況很重要。

+0

我試過這個,但我得到一個異常「過程或函數InsertPerson有太多的參數指定。」。對不起,應該在問題中提出這個問題。 – Fermin

+0

@Fermin當參數包含的參數比存儲過程中聲明的參數個數更多時,會出現異常。由於您將'person'作爲模板傳遞給'DynamicParameters'構造函數,因此'Person'類的所有屬性都有一個爲其生成的參數。所以我懷疑你的班上有更多的屬性,而不僅僅是'ID','Name'和'DOB'。如果是這種情況,那麼我認爲你需要自己指定參數,通過添加它們,如上所示。 –

+0

我很懷疑,我正在嘗試編寫一個通用的DataAccess類,並試圖避免單獨指定參數。 – Fermin

相關問題