Utilisation de Dapper QueryMultiple dans Oracle

dapper oracle

Question

J'essaie d'utiliser dapper avec Oracle (ODP.NET) et j'aimerais utiliser la fonctionnalité "QueryMultiple".

Passer cette chaîne à la méthode QueryMultiple:

 var query = "Select CUST_ID CustId from Customer_info WHERE CUST_ID=:custId;" +
                   "Select CUST_ID CustId from BCR WHERE CUST_ID=:custId";

Je reçois un ORA-00911: erreur de caractère non valide

Est-il possible de faire cela ou ce n'est pas possible?

Tks

Réponse populaire

Le problème a probablement déjà été résolu depuis longtemps par le PO, mais pour l’instant, cette question n’a qu’une réponse et ne résout pas vraiment le problème de l’utilisation de la méthode QueryMultiple() de Dapper avec Oracle. Comme @ Kamolas81 l'indique correctement, en utilisant la syntaxe des exemples officiels, on obtiendra en effet le message d'erreur ORA-00933: SQL command not properly ended . J'ai passé un certain temps à chercher une sorte de documentation sur la façon de faire QueryMultiple() avec Oracle, mais j'ai été surpris de constater QueryMultiple() ne QueryMultiple() une réponse. J'aurais pensé que c'était une tâche assez commune. Je pensais que je posterais une réponse ici pour me sauver :) quelqu'un dans le futur au cas où quelqu'un aurait le même problème.

Dapper semble simplement transmettre la commande SQL directement à ADO.NET et à tout fournisseur de base de données exécutant la commande. Dans la syntaxe des exemples, dans laquelle chaque commande est séparée par un saut de ligne, le serveur SQL l'interprète comme plusieurs requêtes à exécuter sur la base de données et exécute chacune des requêtes et renvoie les résultats dans des sorties séparées. Je ne suis pas un expert ADO.NET, je risque donc de me tromper de terminologie, mais l’effet final est que Dapper récupère les multiples résultats de la requête, puis fonctionne de manière magique.

Cependant, Oracle ne reconnaît pas les multiples requêtes. il pense que la commande SQL est mal formée et renvoie le message ORA-00933 . La solution consiste à utiliser des curseurs et à renvoyer la sortie dans une collection DynamicParameters. Par exemple, alors que la version de SQL Server ressemblerait à ceci:

var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

la version Oracle de la requête devrait ressembler à ceci:

var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
                "OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
                "OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
          "END;";

Pour les requêtes exécutées sur SQL Server, Dapper peut les gérer à partir de là. Cependant, comme nous retournons les jeux de résultats dans les paramètres de curseur, nous devrons utiliser une collection IDynamicParameters pour spécifier les paramètres de la commande. Pour ajouter une ride supplémentaire, la méthode normale DynamicParameters.Add() dans Dapper utilise un System.Data.DbType pour le paramètre facultatif dbType, mais les paramètres de curseur pour la requête doivent être de type Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor . Pour résoudre ce problème, j'ai utilisé la solution proposée par @Daniel Smith dans cette réponse et créé une implémentation personnalisée de l'interface IDynamicParameters :

using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;

public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
    private readonly DynamicParameters dynamicParameters = new DynamicParameters();

    private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();

    public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction, object value = null, int? size = null)
    {
        OracleParameter oracleParameter;
        if (size.HasValue)
        {
            oracleParameter = new OracleParameter(name, oracleDbType, size.Value, value, direction);
        }
        else
        {
            oracleParameter = new OracleParameter(name, oracleDbType, value, direction);
        }

        oracleParameters.Add(oracleParameter);
    }

    public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction)
    {
        var oracleParameter = new OracleParameter(name, oracleDbType, direction);
        oracleParameters.Add(oracleParameter);
    }

    public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
    {
        ((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);

        var oracleCommand = command as OracleCommand;

        if (oracleCommand != null)
        {
            oracleCommand.Parameters.AddRange(oracleParameters.ToArray());
        }
    }
}

Donc tout le code ensemble ressemble à ceci:

using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;

int selectedId = 1;
var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
                "OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
                "OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
          "END;";

OracleDynamicParameters dynParams = new OracleDynamicParameters();
dynParams.Add(":rslt1", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt2", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt3", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":id", OracleDbType.Int32, ParameterDirection.Input, selectedId);

using (IDbConnection dbConn = new OracleConnection("<conn string here>"))
{
    dbConn.Open();
    var multi = dbConn.QueryMultiple(sql, param: dynParams);

    var customer = multi.Read<Customer>().Single();
    var orders = multi.Read<Order>().ToList();
    var returns = multi.Read<Return>().ToList();
    ...
    dbConn.Close();
}


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