Posso usare DynamicParameters con Template e avere un parametro di ritorno in dapper?

.net c# dapper

Domanda

Il sistema su cui sto lavorando attualmente utilizza stored procedure per tutti gli accessi ai dati. Sto cercando Dapper al momento (finora sembra fantastico), ma mi chiedevo se posso usare un oggetto DynamicParameters creato usando un Template ma rendere uno dei parametri un parametro di output. Per esempio:

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

Codice:

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

Corrente Ricevo un errore perché la chiave non è stata trovata. C'è un modo per ottenere il parametro di output ID senza impostare manualmente tutti i parametri procs memorizzati?

Risposta accettata

Con un rapido aggiustamento, Add ora sostituisce il valore di un modello, consentendo:

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

È abbastanza vicino? È inoltre possibile utilizzare ParameterDirection.ReturnValue , di un valore preesistente o di un nuovo valore. Nota che non si aggiorna direttamente nel modello originale; il valore deve essere recuperato DynamicParameters (come mostrato).


Risposta popolare

Quando si utilizza il costruttore per DynamicParameters per specificare un oggetto modello, sarà comunque necessario specificare che @ID è un parametro di output. Inizialmente, tramite il modello, verrà impostato su ParameterDirection.Input . Dopo averlo aggiunto, verrà sovrascritto per avere i valori aggiornati, quindi è possibile ottenere il valore dal nome del parametro come segue:

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

Sono stato in grado di farlo funzionare e ho usato classi e codice, oltre a quello che ho mostrato sopra.

EDIT: come discusso nei commenti, la stored procedure non accetta più argomenti di quanti ne abbia dichiarati. Pertanto, un approccio alternativo è quello di abbandonare la stored procedure e ricorrere a qualche SQL in linea. Quando si utilizza una query Dapper ignorerà tutti i parametri forniti che non sono specificati nell'istruzione SQL. Questo è un work-around per affrontare questo problema:

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;

Nota che SCOPE_IDENTITY() restituisce un decimale, non un int.

Un'altra idea, che ritengo non sia ideale, consiste nel modificare il codice Dapper e aggiungere un metodo Remove alla classe DynamicParameters per rimuovere parametri indesiderati. Questo non ti fa risparmiare molto, dal momento che ti dedichi ancora del tempo a specificare quali parametri rimuovere tutti allo scopo di rendere felice una stored procedure. Se si decide di implementarlo, ricordare che il caso è importante quando si specifica la chiave da rimuovere dal dizionario dei parameters .



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché