Dapper appelle sp_executesql quand j'ai des paramètres, y a-t-il un moyen de contourner cela?

dapper

Question

Quand j'appelle

connection.Execute(sql);

Dapper s'exécute et tout va bien. Quand j'appelle

connection.Execute(sql, new { UserId = _userId });

il s'exécute avec sp_executesql.

Le problème est qu'il utilise sp_executesql dans sa propre portée. S'il crée une table temporaire, elle n'est pas accessible aux requêtes suivantes qui utilisent la même connexion. Je pourrais contourner ce problème en utilisant des tables temporaires globales, mais je ne veux pas risquer que deux processus interfèrent les uns avec les autres.

Quelqu'un sait-il comment contourner cela?

Mise à jour: J'ai le même problème lorsque j'utilise des objets SqlCommand sans Dapper. J'ai écrit un test unitaire qui illustre le problème que j'ai. WorksWithParameters échoue avec System.Data.SqlClient.SqlException: nom d'objet non valide '#TEMP_OBJECTLIST'.

[TestFixture]
public class DapperTest
{
    private const string TestObjectType = "S";
    private const string ConnectionString = "XXXXXXXXX";

    private static void CreateTempTableWithoutParameters(SqlConnection connection)
    {
        const string sql = "SELECT TOP 10 * INTO #TEMP_OBJECTLIST FROM sys.objects WHERE TYPE = 'S'";
        connection.Execute(sql);
    }

    private static void UseTempTableWithoutParameters(SqlConnection connection)
    {
        const int expectedCount = 10;

        const string sql = "SELECT COUNT(*) FROM #TEMP_OBJECTLIST WHERE TYPE = 'S'";
        var count = connection.Query<int>(sql).First();

        Assert.AreEqual(expectedCount, count);
    }

    private static void CreateTempTableWithParameters(SqlConnection connection)
    {
        const string sql = "SELECT TOP 10 * INTO #TEMP_OBJECTLIST FROM sys.objects WHERE TYPE = @OBJECT_TYPE";
        connection.Execute(sql, new {OBJECT_TYPE = TestObjectType});
    }

    private static void UseTempTableWithParameters(SqlConnection connection)
    {
        const int expectedCount = 10;

        const string sql = "SELECT COUNT(*) FROM #TEMP_OBJECTLIST WHERE TYPE = @OBJECT_TYPE";
        var param = new {OBJECT_TYPE = TestObjectType};

        var count = connection.Query<int>(sql, param).First();

        Assert.AreEqual(expectedCount, count);
    }

    [Test]
    public void WorksWithParameters()
    {
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();

            CreateTempTableWithParameters(connection);
            UseTempTableWithParameters(connection);
        }
    }

    [Test]
    public void WorksWithoutParameters()
    {
        using (var connection = new SqlConnection(ConnectionString))
        {
            connection.Open();

            CreateTempTableWithoutParameters(connection);
            UseTempTableWithoutParameters(connection);
        }
    }
}

Réponse populaire

Une solution au problème de l'étendue de la table temporaire consiste à créer la table temporaire avec une colonne factice dans la portée externe, puis à utiliser les instructions alter table pour ajouter toutes les colonnes souhaitées et l'utiliser.

De plus, comment partager des données entre des procédures par Erland Sommarskog peut être utile à vous ou à une autre personne à la recherche de différentes options de partage de données.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi