76 votes

Dapper prend-il en charge les paramètres SQL 2008 évalués par table ?

Quelqu'un sait-il s'il est possible de passer paramètre à valeur de tableau vers une procédure stockée avec Dapper ?

89voto

Marc Gravell Points 482669

Il y a maintenant (dans Dapper 1.26 et plus) un support direct pour les paramètres à valeur de table intégrés dans Dapper. Dans le cas des procédures stockées, puisque le type de données est intégré à l'API sproc, tout ce que vous avez à faire est de fournir un paramètre de type DataTable :

var data = connection.Query<SomeType>(..., new {
    id=123, name="abc", values = someTable
}, ...);

Pour la commande directe de texte, deux autres options s'offrent à vous :

  • utiliser une méthode d'aide pour lui indiquer le type de données personnalisé :

    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable.AsTableValuedParameter("mytype")
    }, ...);
  • indiquent à la table de données elle-même le type de données personnalisé à utiliser :

    someTable.SetTypeName("mytype");
    var data = connection.Query<SomeType>(..., new {
        id=123, name="abc", values = someTable
    }, ...);        

N'importe lequel d'entre eux devrait faire l'affaire.

28voto

Sam Saffron Points 56236

Oui, nous les soutenons, mais vous devrez coder vos propres aides.

Par exemple :

class IntDynamicParam : Dapper.SqlMapper.IDynamicParameters
{
    IEnumerable<int> numbers;
    public IntDynamicParam(IEnumerable<int> numbers)
    {
        this.numbers = numbers;
    }

    public void AddParameters(IDbCommand command)
    {
        var sqlCommand = (SqlCommand)command;
        sqlCommand.CommandType = CommandType.StoredProcedure;

        List<Microsoft.SqlServer.Server.SqlDataRecord> number_list = new List<Microsoft.SqlServer.Server.SqlDataRecord>();

        // Create an SqlMetaData object that describes our table type.
        Microsoft.SqlServer.Server.SqlMetaData[] tvp_definition = { new Microsoft.SqlServer.Server.SqlMetaData("n", SqlDbType.Int) };

        foreach (int n in numbers)
        {
            // Create a new record, using the metadata array above.
            Microsoft.SqlServer.Server.SqlDataRecord rec = new Microsoft.SqlServer.Server.SqlDataRecord(tvp_definition);
            rec.SetInt32(0, n);    // Set the value.
            number_list.Add(rec);      // Add it to the list.
        }

        // Add the table parameter.
        var p = sqlCommand.Parameters.Add("@ints", SqlDbType.Structured);
        p.Direction = ParameterDirection.Input;
        p.TypeName = "int_list_type";
        p.Value = number_list;

    }
}

// SQL Server specific test to demonstrate TVP 
public void TestTVP()
{
    try
    {
        connection.Execute("CREATE TYPE int_list_type AS TABLE (n int NOT NULL PRIMARY KEY)");
        connection.Execute("CREATE PROC get_ints @ints int_list_type READONLY AS select * from @ints");

        var nums = connection.Query<int>("get_ints", new IntDynamicParam(new int[] { 1, 2, 3 })).ToList();
        nums[0].IsEqualTo(1);
        nums[1].IsEqualTo(2);
        nums[2].IsEqualTo(3);
        nums.Count.IsEqualTo(3);
        connection.Execute("DROP PROC get_ints");
        connection.Execute("DROP TYPE int_list_type");

    }
}

Veillez à tester correctement les performances des paramètres évalués en fonction de la table. Lorsque j'ai testé cela pour passer des listes d'int, c'était significativement plus lent que de passer des paramètres multiples.

Je ne suis pas du tout opposé à l'idée d'avoir des aides spécifiques à SQL Server pour dapper dans le projet contributif, mais le noyau de dapper évite d'ajouter des astuces spécifiques au fournisseur lorsque c'est possible.

10voto

Darek Points 1841

Je sais que ce ticket est ANCIEN, très ancien, mais je voulais vous faire savoir que j'ai publié le package Dapper.Microsoft.Sql, qui supporte les TVP génériques.

https://www.nuget.org/packages/Dapper.Microsoft.Sql/

Exemple d'utilisation :

List<char> nums = this.connection.Query<char>(
  "get_ints", 
  new TableValuedParameter<char>(
    "@ints", "int_list_Type", new[] { 'A', 'B', 'C' })).ToList();

Il est basé sur les classes originales du projet de test Dapper.

Profitez-en !

5voto

Marc Gravell Points 482669

aujourd'hui ce n'est pas le cas. Nous avons en fait étudié les paramètres validés par la table pour notre implémentation "in" effrontée ( where col in @values ), mais ils n'ont pas été impressionnés par les performances. Cependant, dans le contexte d'un SPROC, cela a du sens.

La meilleure solution est de enregistrer cette question sur le site du projet afin que nous puissions le suivre et le classer par ordre de priorité. Il semble que quelque chose soit faisable, probablement similaire aux options DbString ou DynamicParameters.

Mais aujourd'hui ? Non.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X