Oracle에서 Dapper QueryMultiple 사용
Oracle(ODP.NET)과 함께 dapper를 사용하려고 하는데 "QueryMultiple" 기능을 사용하고 싶습니다.
이 문자열을 QueryMultiple 메서드에 전달:
var query = "Select CUST_ID CustId from Customer_info WHERE CUST_ID=:custId;" +
"Select CUST_ID CustId from BCR WHERE CUST_ID=:custId";
ORA-00911이 표시됩니다. 잘못된 문자 오류입니다.
이것을 할 수 있는 방법이 있습니까 아니면 불가능합니까?
Tks
OP는 아마도 지금쯤이면 문제를 해결한 지 오래되었을 것입니다만, 글을 쓰는 시점에서 이 질문은 답이 하나밖에 없고 Dapper's를 사용하는 문제를 실제로 해결하지는 못합니다.QueryMultiple()
메서드와 오라클이 함께 사용됩니다.@Kamolas81이 정확하게 언급했듯이, 공식 예제의 구문을 사용하면 실제로 다음을 얻을 수 있습니다.ORA-00933: SQL command not properly ended
오류 메시지입니다.어떻게 해야 하는지에 대한 문서 같은 것을 찾느라 잠시 시간을 보냈습니다.QueryMultiple()
오라클과 함께 했는데, 답이 있는 곳이 한 곳도 없어서 놀랐어요.저는 이것이 꽤 흔한 일이라고 생각했을 것입니다.여기에 글을 올려 저장하려고 했습니다.
나 :) 미래의 누군가가 이와 같은 문제를 겪을 경우를 대비하여.
Dapper는 SQL 명령을 ADO.NET 및 명령을 실행 중인 모든 DB 공급자에게 바로 전달하는 것 같습니다.각 명령이 줄 바꿈으로 구분된 예제의 구문에서 SQL 서버는 데이터베이스에 대해 실행할 여러 쿼리로 해석하고 각 쿼리를 실행하여 결과를 별도의 출력으로 반환합니다.저는 ADO.NET 전문가가 아니기 때문에 용어를 엉망으로 만들 수도 있지만, 최종적인 효과는 Dapper가 여러 개의 쿼리 출력을 얻은 다음 마법을 사용한다는 것입니다.
그러나 Oracle은 여러 쿼리를 인식하지 못합니다. SQL 명령이 잘못되었다고 생각하고 다음을 반환합니다.ORA-00933
메세지.솔루션은 커서를 사용하고 동적 파라미터 컬렉션에서 출력을 반환하는 것입니다.예를 들어 SQL Server 버전은 다음과 같습니다.
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
Oracle 버전의 쿼리는 다음과 같습니다.
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;";
SQL Server에 대해 실행되는 쿼리의 경우 Dapper는 여기서 쿼리를 처리할 수 있습니다.그러나 결과 집합을 커서 매개 변수로 되돌리기 때문에 다음을 사용해야 합니다.IDynamicParameters
명령에 대한 매개 변수를 지정하는 컬렉션입니다.주름을 추가하려면 보통DynamicParameters.Add()
Dapper의 메서드는 시스템을 사용합니다.인 dbType대한 는 "dbType " 데이터" 유형이어야 .DbType이지만 쿼리의 커서 매개 변수는 유형이어야 합니다.Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor
이를 해결하기 위해 @Daniel Smith가 이 답변에서 제안한 솔루션을 사용하고 사용자 정의 구현을 만들었습니다.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());
}
}
}
그래서 모든 코드는 다음과 같이 진행됩니다.
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();
}
Greyseal96의 유용한 답변을 바탕으로 이 구현을 만들었습니다.IDynamicParameters
:
public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
private readonly DynamicParameters dynamicParameters;
private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
public OracleDynamicParameters(params string[] refCursorNames) {
dynamicParameters = new DynamicParameters();
AddRefCursorParameters(refCursorNames);
}
public OracleDynamicParameters(object template, params string[] refCursorNames) {
dynamicParameters = new DynamicParameters(template);
AddRefCursorParameters(refCursorNames);
}
private void AddRefCursorParameters(params string[] refCursorNames)
{
foreach (string refCursorName in refCursorNames)
{
var oracleParameter = new OracleParameter(refCursorName, OracleDbType.RefCursor, ParameterDirection.Output);
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());
}
}
}
동일한 쿼리를 가정하면 다음과 같이 사용할 수 있습니다.
var queryParams = new { id };
string[] refCursorNames = { "rslt1", "rslt2", "rslt3" };
var dynParams = new OracleDynamicParameters(queryParams, refCursorNames);
...
var multi = dbConn.QueryMultiple(sql, param: dynParams);
저는 이것이 두 개 또는 세 개의 분리된 것이라고 생각합니다.
- 첫 번째 쿼리에는 세미콜론이 없어야 합니다.
- 쿼리 사이에 줄 바꿈 문자가 없습니다.
- 사용 참고 사항은 바인딩 문자가 다음과 같다는 것을 의미합니다.
@
것은 아니다.:
(이것이 사용 중인 RDBMS에 따라 달라지는지 여부는 알 수 없음).
Dapper Google Code 페이지를 보면 다음과 같은 예가 있습니다.QueryMultiple()
다음과 같습니다.
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}
세미콜론을 제거하고 새 줄을 추가한 후에도 문제가 있으면 바인딩 문자를 변경합니다.
언급URL : https://stackoverflow.com/questions/18772781/using-dapper-querymultiple-in-oracle
'programing' 카테고리의 다른 글
스프링 부트:JPA/Hibernate 주석에서 DDD 엔티티를 깨끗하게 유지하는 방법은 무엇입니까? (0) | 2023.07.01 |
---|---|
회전된 xtick 라벨과 해당 xtick 라벨 정렬 (0) | 2023.07.01 |
Mac에서 VBA(Excel) 사전? (0) | 2023.07.01 |
VBA에서 As를 사용하여 유형을 지정하여 여러 변수를 선언하는 방법은 무엇입니까? (0) | 2023.07.01 |
SQL Server 프로시저가 목록 선언 (0) | 2023.07.01 |