I Have a stored procedure:
CREATE OR REPLACE PROCEDURE UpdateFileMapping(field in number, original_Field_Names in DBMS_SQL.varChar2_table, mapped_Field_Ids in DBMS_SQL.number_table)
IS
C NUMBER := DBMS_SQL.OPEN_CURSOR;
N NUMBER;
BEGIN
DBMS_SQL.PARSE(C,'INSERT INTO input_file_mapping VALUES(input_file_mapping_id.NextVal, 3, field, :fieldName, :mappedFieldId)', DBMS_SQL.NATIVE);
DBMS_SQL.BIND_ARRAY(C,':fieldName', original_Field_Names);
DBMS_SQL.BIND_ARRAY(C,':mappedFieldId', mapped_Field_Ids);
N := DBMS_SQL.EXECUTE(C);
DBMS_SQL.CLOSE_CURSOR(C);
END;
How to call such procedure which takes as input of DBMS_SQL.varChar2_table type from C#?
You need to include the proper ODP.NET provider for your system and then use OracleConnection and OracleCommand types to create a connection and execute the stored procedure. ODP.NET comes with extensive documentation and many examples.
Try:
void ExecOracleStoredProcedure(int field, string[] original_Field_Names, int[] mapped_Field_Ids)
{
using (OracleConnection connection = new OracleConnection(connectionString))
using (OracleCommand command = connection.CreateCommand())
{
command.CommandText = "UpdateFileMapping";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue(":field").Value = field;
command.Parameters.AddWithValue(":original_Field_Names").Value = original_Field_Names;
command.Parameters.AddWithValue(":mapped_Field_Ids").Value = mapped_Field_Ids;
connection.Open();
command.ExecuteNonQuery();
}
}
Looks like Enterprise Library from MS still support Oracle Database
For the Data Access Application Block, the following is also required:
A database server running a database that is supported by a .NET Framework 3.5 with Service Pack 1 or .NET Framework 4.0 data provider. This includes SQL ServerĀ® 2000 or later, SQL Server 2005 Compact Edition, and Oracle 9i or later. The database server can also run a database that is supported by the .NET Framework 3.5 with Service Pack 1 or the .NET Framework 4.0 data providers for OLE DB or ODBC.
create or replace procedure UpdateFileMapping(m in Number,y in DBMS_SQL.varChar2_table,z in DBMS_SQL.number_table)
IS
C NUMBER;
N NUMBER;
BEGIN
C := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(C,'INSERT INTO tablename VALUES(:x ,:fieldName,:mappedFieldId)',DBMS_SQL.NATIVE);
DBMS_SQL.BIND_ARRAY(C,':fieldName',original_Field_Names);
DBMS_SQL.BIND_ARRAY(C,':mappedFieldId',mapped_Field_Ids);
DBMS_SQL.BIND_VARIABLE(C,':x',file_Id);
N := DBMS_SQL.EXECUTE(C);
DBMS_SQL.CLOSE_CURSOR(C);
END;
For more information:
http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28419/d_sql.htm
Related
Steps to reproduce:
var s = #"USE `my_schema`;
DROP procedure IF EXISTS `new_procedure`;
DELIMITER $$
USE `my_schema`$$
CREATE PROCEDURE `new_procedure` ()
BEGIN
select 1;
END$$
DELIMITER ;
";
await dbContext.Database.ExecuteSqlRawAsync(s);
Exception:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DELIMITER $$
CREATE DEFINER=root#% PROCEDURE new_procedure()
MySQL version: 8.0.21
Microsoft.EntityFrameworkCore version: 5.0.8
Pomelo.EntityFrameworkCore.MySql version: 5.0.0
.NET version: 5.0.302
From https://mysqlconnector.net/troubleshooting/delimiter/:
This limitation does not exist in MySqlConnector, so using DELIMITER is unnecessary and it must be removed (to avoid sending invalid SQL to the server).
To fix the problem, remove the DELIMITER declaration and any trailing instances of the delimiter:
var s = #"USE `my_schema`;
DROP procedure IF EXISTS `new_procedure`;
CREATE PROCEDURE `new_procedure` ()
BEGIN
select 1;
END;
";
await dbContext.Database.ExecuteSqlRawAsync(s);
You have to use MySqlScript class, but Pomelo driver uses MySqlConnector library, which not included realisation in the library tracking Issue
But you can copy it's realisation from Oracle's source:
https://github.com/mysql/mysql-connector-net/blob/6.9/Source/MySql.Data/MySqlScript.cs
Usage is simple:
using (var connection = new MySqlConnection(connectionString))
{
var script = new MySqlScript(connection, scriptText);
connection.Open();
script.Execute();
}
Assume we have a stored procedure like so
CREATE PROCEDURE CopyValue(IN src INT, OUT dest INT)
BEGIN
SET dest = src;
END
I want to call this from a .net app (assume connection etc created successfully)
var sql = "call CopyValue(100, #destValue); select #destValue as Results;";
The string in the above statement works perfectly well when called in MySql Workbench.
However this - obviously - fails with "MySqlException: Parameter '#destValue' must be defined" when executed on a MySqlCommand object in .net
How do I arrange this statement so I can capture an output parameter from an existing procedure?
NB: I'm running against MySql 5.6, which I can't upgrade at this time.
NB Calling the procedure directly with CommandType.StoredProcedure goes against company guidelines.
By default, user-defined variables aren't allowed in SQL statements by MySQL Connector/NET. You can relax this restriction by adding AllowUserVariables=true; to your connection string. No modifications to your SQL or how you're executing the MySqlCommand should be necessary.
For information about why this is the default, you can read the research on this MySqlConnector issue (which also has the same default behaviour, but a much better error message that will tell you how to solve the problem): https://github.com/mysql-net/MySqlConnector/issues/194
A colleague (who wishes to remain anonymous) has answered this perfectly. Essentially put backticks ` after the # and at the end of the variable name e.g.
#`MyParam`
A fully working example.
static void Main(string[] args)
{
using var con = new MySql.Data.MySqlClient.MySqlConnection("Data Source=localhost; User Id=...;Password=...;Initial Catalog=...");
con.Open();
using var cmd = con.CreateCommand();
cmd.CommandText = "call CopyValue2(100, #`v2`); select #`v2` as Results;";
using var reader = cmd.ExecuteReader();
if (reader.Read())
Console.WriteLine($"Copied Value {reader.GetInt64(0)}");
}
Thanks OG :)
OracleConnection connection = DBHelper.OracleConnection;
OracleCommand OraCommand = connection.CreateCommand();
OraCommand.CommandText = "AUTHENTICATION.Authenticate";
OraCommand.CommandType = CommandType.StoredProcedure;
int zero = 0;
OracleParameter newParam = null;
OraCommand.Parameters.Add(newParam);
newParam = new OracleParameter("Authenticated", OracleType.VarChar);
newParam.Direction = ParameterDirection.Output;
newParam.Size = 4000;
OraCommand.Parameters.Add(newParam);
newParam = new OracleParameter("Message", OracleType.VarChar);
newParam.Direction = ParameterDirection.Output;
newParam.Size = 4000;
OraCommand.Parameters.Add(newParam);
newParam = new OracleParameter("Response", OracleType.VarChar);
newParam.Direction = ParameterDirection.Output;
newParam.Size = 4000;
OraCommand.Parameters.Add(newParam);
try
{
connection.Open();
OraCommand.ExecuteNonQuery();
connection.Close();
errorLabel.Text = OraCommand.Parameters["Message"].Value.ToString() ;
if (OraCommand.Parameters["Authenticated"].Value.ToString() == "Yes")
{
this.Response.Redirect("Default.aspx", true);
}else
{
errorLabel.Text = OraCommand.Parameters["Message"].Value.ToString() + Request.ServerVariables["SERVER_SOFTWARE"] + OraCommand.Parameters[9].Value.ToString();
}
}
catch (Exception ex)
{
errorLabel.Text = ex.ToString();
}
Expected outputs:
1) Message - You have successfully logged in
but I'm getting a truncated string: You have success
2) Authenticated - Yes
but I'm getting a truncated string
Y
Same code worked fine in IIS 7.5, we upgraded our server to IIS 8.5 now I'm facing this problem .
I did read some articles about ado.net deprecated and use odp.net . I dont want to change my code to ODP.net .
Do you have any thoughts , why my output variables are truncated ??
When we upgraded IIS 8.5 we installed 12.1.0 instant client on that machine. Does this cause the problem ???
This is the bug in Oracle Client 12c. It truncates not only strings but numbers as well. Reverting to client 11g fixed the problem.
newParam = new OracleParameter("Response",OracleType.VarChar);
Use **OracleType.Char** instead of **OracleType.VarChar**
newParam = new OracleParameter("Response", OracleType.Char);
IT works in my case.
I am using Oracle 11g and VS12 ,truncating output parameter in dot net code,
I even changed the output parameter as integer in Stored procedure.
When I changed to Char instead of Varchar as below in dot net it works fine.
db.AddParameter(dbCommand, "p_out_result", OracleType.Char, 300,
ParameterDirection.Output, true, 100, 3, null, DataRowVersion.Default, null);
We had the same experiance as you did when migrating to Oracle 12c database (on Oracle servers) and to a Windows 2012 for webservices (IIS 8).
Varchar2 string, returned from a stored procedure, was truncated almost always at half - no mather what setting we used.
Replacing the Oracle client 12 64-bit with client 12 32-bit did NOT solve the problem.
The solution of Vick Rom solved our problem. Oracle client 11 was installed on a 64bit Windows 2012 server.
We are planning to keep it that way until Oracle client 12 won't be fixed.
I have the same problem, But I found a work around while you still using oracle 12 and 11 installed on the same machine. below is what I did.
1- Oracle 11 was already installed in my case so I keep it there.
2- I installed oracle client 12c. copied the TNS names after the installation.
3- Installed oracle 11 (win32_11gR2_client). copied the TNS names files.
4- restarted the server.
Everything worked very well. the system using oracle client managed driver worked and the old system using system.data.oracleclient worked as well.
Thank you
I had the same issue, but chose a different approach due to my client's policy to stick with latest Oracle Client. In this case, I have to make my code work with Oracle 12c client on Windows 2012 R2 [IIS 8.5] server.
Instead of returning a varchar2 as output paramter, I modified the SP to return a SYS_REFCURSOR with one row/column in it.
Ex:
PROCEDURE get_access_sp (p_mode IN VARCHAR2, p_out OUT SYS_REFCURSOR)
IS
BEGIN
/*Body of SP*/
v_out := 'TEST_SP_RETURN_PARAM';
--RETURN
OPEN p_out FOR SELECT v_out po FROM DUAL;
EXCEPTION
WHEN OTHERS
THEN
OPEN p_out FOR SELECT 'N' po FROM DUAL;
END get_access_sp;
Im trying to call a Oracle stored proc from a C# application using the following code
Connection conn = new Connection();
Recordset rs = new Recordset();
conn.Open("Provider=MSDAORA;User Id=username;Password=password;Data Source=DB;", null, null, 0); ;
rs.Open("sproc 'abc', 'xyz'", conn, ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockReadOnly, -1);
where abc and xyz are input parameters..
However, I get "invalid SQL statement exception" when I try to run it..
Is there any other way to execute a oracle stored proc. I can execute MSSQL stored procs or normal Oracle queries in the same way described above..
I even tried using createparameter, but that didn't help either
Thanks,
Sam
Grab the Oracle ODP.NET tools: http://www.oracle.com/technology/software/tech/windows/odpnet/index.html
They are what I use to interact with our Oracle database from my ASP.NET application
Check here for an example of calling an Oracle stored procedure in C#.
Basically, with the package:
// Create oracle command object for the stored procedure
OracleCommand cmd = new OracleCommand("HR_DATA.GETCURSORS", conn);
cmd.CommandType = CommandType.StoredProcedure;
// Enter a parameter for the procedure
OracleParameter dep_id = new OracleParameter();
dep_id.OracleDbType = OracleDbType.Decimal;
dep_id.Direction = ParameterDirection.Input;
dep_id.Value = 60;
cmd.Parameters.Add(dep_id);
// Add more parameters ...
// Execute the stored procedure
Here's a link to the API documentation
Nevermind.. Apparently I was missing brackets around input parameters...
Thanks,
Sam
My development machine is running Windows 7 Enterprise, 64-bit version. I am using Visual Studio 2010 Release Candidate. I am connecting to an Oracle 11g Enterprise server version 11.1.0.7.0. I had a difficult time locating Oracle client software that is made for 64-bit Windows systems and eventually landed here to download what I assume is the proper client connectivity software. I added a reference to "Oracle.DataAccess" which is version 2.111.6.0 (Runtime Version is v2.0.50727). I am targeting .NET CLR version 4.0 since all properties of my VS Solution are defaults and this is 2010 RC. I was then able to write a console application in C# that established connectivity, executed a SELECT statement, and properly returned data when the table in question does NOT contain a spatial column. My problem is that this no longer works when the table I query has a column of type SDO_GEOMETRY in it.
Below is the simple console application I am trying to run that reproduces the problem. When the code gets to the line with the "ExecuteReader" command, an exception is raised and the message is "Unsupported column datatype".
using System;
using System.Data;
using Oracle.DataAccess.Client;
namespace ConsoleTestOracle
{
class Program
{
static void Main(string[] args)
{
string oradb = string.Format("Data Source={0};User Id={1};Password={2};",
"hostname/servicename", "login", "password");
try
{
using (OracleConnection conn = new OracleConnection(oradb))
{
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "select * from SDO_8307_2D_POINTS";
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
}
}
catch (Exception e)
{
string error = e.Message;
}
}
}
}
The fact that this code works when used against a table that does not contain a spatial column of type SDO_GEOMETRY makes me think I have my windows 7 machine properly configured so I am surprised that I get this exception when the table contains different kinds of columns. I don't know if there is some configuration on my machine or the Oracle machine that needs to be done, or if the Oracle client software I have installed is wrong, or old and needs to be updated.
Here is the SQL I used to create the table, populate it with some rows containing points in the spatial column, etc. if you want to try to reproduce this exactly.
SQL Create Commands:
create table SDO_8307_2D_Points (ObjectID number(38) not null unique, TestID number, shape SDO_GEOMETRY);
Insert into SDO_8307_2D_Points values (1, 1, SDO_GEOMETRY(2001, 8307, null, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(10.0, 10.0)));
Insert into SDO_8307_2D_Points values (2, 2, SDO_GEOMETRY(2001, 8307, null, SDO_ELEM_INFO_ARRAY(1, 1, 1), SDO_ORDINATE_ARRAY(10.0, 20.0)));
insert into user_sdo_geom_metadata values ('SDO_8307_2D_Points', 'SHAPE', SDO_DIM_ARRAY(SDO_DIM_ELEMENT('Lat', -180, 180, 0.05), SDO_DIM_ELEMENT('Long', -90, 90, 0.05)), 8307);
create index SDO_8307_2D_Point_indx on SDO_8307_2D_Points(shape) indextype is mdsys.spatial_index PARAMETERS ('sdo_indx_dims=2' );
Any advice or insights would be greatly appreciated. Thank you.
Here is a link to a post with a sample app using C# and ODP.net to access spatial types.
http://www.orafaq.com/forum/mv/msg/27794/296419/0/#msg_296419
There is also a sample here about using XML to select the spatial types:
http://forums.oracle.com/forums/thread.jspa?threadID=241076