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

L'OP a probablement résolu le problème depuis longtemps, mais au moment de l'écriture, cette question n'a qu'une seule réponse et ne résout pas vraiment le problème de l'utilisation de la méthode QueryMultiple() de Oracle avec Oracle. Comme @ Kamolas81 le dit 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é du temps à chercher une sorte de documentation sur la façon de faire QueryMultiple() avec Oracle, mais j'étais surpris de voir qu'il n'y avait pas vraiment un seul endroit pour répondre. 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 juste au cas où quelqu'un aurait le même problème.

Dapper semble simplement passer la commande SQL directement à ADO.NET et à tout fournisseur de base de données exécutant la commande. Dans la syntaxe des exemples, où chaque commande est séparée par un saut de ligne, SQL Server interprétera cela comme plusieurs requêtes à exécuter sur la base de données et exécutera chacune des requêtes et renverra les résultats dans des sorties séparées. Je ne suis pas un expert ADO.NET, donc je vais peut-être dénaturer la terminologie, mais l'effet final est que Dapper obtient les résultats de plusieurs requêtes et ensuite opère sa magie.

Oracle, cependant, ne reconnaît pas les requêtes multiples; 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 le gérer à partir de là. Toutefois, comme nous retournons les jeux de résultats dans les paramètres du curseur, nous devons utiliser une collection IDynamicParameters pour spécifier les paramètres de la commande. Pour ajouter un pli supplémentaire, la méthode DynamicParameters.Add() normale dans Dapper utilise un System.Data.DbType pour le paramètre optionnel 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 va quelque chose comme 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