I've been trying to pass 2 field data type to oracle procedure from c#. I can do it for 1 field like below;
oracle:
TYPE my_array IS TABLE OF VARCHAR2(40) INDEX BY BINARY_INTEGER;
PROCEDURE insert_question(test IN my_array) IS
BEGIN
--something
END;
C#:
command.Parameters.Add(new OracleParameter("test", OracleDbType.Varchar2)
{
CollectionType = OracleCollectionType.PLSQLAssociativeArray,
UdtTypeName = "my_array",
Value = data_list.ToArray(),
Size = data_list.Count,
Direction = ParameterDirection.Input
});
It is ok until here. Now, i need to pass 2 field list to oracle stored procedure like;
number
text
I created a new type named for_questions;
TYPE fields IS RECORD
(
num NUMBER,
text VARCHAR2(1000)
);
TYPE for_questions IS TABLE OF fields INDEX BY BINARY_INTEGER;
and i have a list at c# with 2 field. I've tryed this code for pass data to oracle procedure as parameter;
command.Parameters.Add(new OracleParameter("fixed", OracleDbType.Varchar2)
{
CollectionType = OracleCollectionType.PLSQLAssociativeArray,
UdtTypeName = "for_questions",
Value = fixed_q.ToArray(),
Size = fixed_q.Count,
Direction = ParameterDirection.Input
});
But it doesn't work as expected. So i need some help. How can i pass a 2 field list/array to oracle stored procedure as parameter?
Thanks in advance.
NOTE:Adviced question doesn't helpfull for me because it's on java. My problem is: I can't pass multiple field type as a parameter in c#.
Related
How would I take this query that is in my stored procedure and pass in the correct parameters?
select * from Inventory
where category in (#categories) and qty > #qty and condition in (#conditions)
I seen that I should do something like this
CREATE PROCEDURE [dbo].[usp_DoSomethingWithTableTypedParameter]
(
#categories categories READONLY
#Qty int,
#conditions
)
But how does the ADO.NET side look like? If I were to pass in for categories 'Tools', 'Hardware' and for conditions 'New', 'Used'.
How would I do this?
To add 3 further parameters to your SP, #Qty, #Category & #Condition you just duplicate the steps you've already taken.
Create any additional User Defined Table Types
Both #Category and #Condition need a UDT, #Qty doesn't as it is a native type.
Some people will prefer having a separate UDT each for #Category and #Condition, personally given they both take the same datatype I create a single general purpose utility UDT e.g.
CREATE TYPE [dbo].[udt_ShortString] AS TABLE
(
[Value] [varchar](128) NULL
)
Modify the SP e.g.
CREATE PROCEDURE [dbo].[usp_DoSomethingWithTableTypedParameter]
(
#UserIdList udt_UserId READONLY
, #CategoryList udt_ShortString READONLY
, #ConditionList udt_ShortString READONLY
, #Qty int
)
AS
Add the values to your command object, where you load the new datatables exactly the same as you are already loading your existing userId table e.g.
cmd.Parameters.Add(new SqlParameter("#UserIdList", System.Data.SqlDbType.Structured) { TypeName = "udt_UserId", Value = userIdList });
cmd.Parameters.Add(new SqlParameter("#CategoryList", System.Data.SqlDbType.Structured) { TypeName = "udt_ShortString", Value = categoryList });
cmd.Parameters.Add(new SqlParameter("#ConditionList", System.Data.SqlDbType.Structured) { TypeName = "udt_ShortString", Value = conditionList });
cmd.Parameters.Add(new SqlParameter("#Qty", SqlDbType.Int) { Value = qty });
Note: For clarity I have hardcoded the parameter names and type names in - you are of course free to pass them as variabled as you were doing.
It looks like it's possible to have an Oracle command in C# which has an output parameter, however if it is I'm not sure how to wire it up.
The command:
declare
type new_rows is table of Table1%rowtype;
newRows new_rows;
type newKeys_rec is record (col1 number, col2 number);
type newKeys_type is table of newKeys_rec;
newKeys newKeys_type;
begin
select *
bulk collect into newRows
from Table2;
forall idx in 1..newRows.count()
insert into Table1
values newRows(idx)
returning Table1.col1, Table1.col2 bulk collect into newKeys;
end;
The command parameter in sql:
Parameters.Add(new OracleParameter
{
ParameterName = "newKeys",
ObjectTypeName = "newKeys_type",
OracleDbType = OracleDbType.Object,
Direction = ParameterDirection.Output
});
The error:
OCI-22303: type ""."NEWKEYS_TYPE" not found
UPDATE: Following upon the answers below:
1) Declare the type on the schema:
Create type Schema.newKeys_object as object (col1 number, Col2 number)
Create type Schema.newKeys_type as table of Schema.type1_object
2) In the OracleParameter:
Parameters.Add(new OracleParameter
{
ParameterName = "newKeys",
ObjectTypeName = "newKeys_type",
OracleDbType = OracleDbType.Table,
Direction = ParameterDirection.ReturnValue
});
In order for the PL/SQL types to be accessible from C# you need to define them as database types using the CREATE TYPE statement. See this Web page for more details on that DDL statement. Note also that a database type belongs to a schema and has access permissions just like a database table has, so when accessing the database type from C# code, you may need to prepend the schema name to the type name, as in...
SCOTT.NEWKEYS_TYPE
I am upgrading my application to Oracle.ManagedDataAccess. I want to pass an array of objects to a stored procedure.
Following is my SP:
CREATE OR REPLACE TYPE MATCHING_CRITERIA_LIST IS TABLE OF CRITERIA;
CREATE OR REPLACE PROCEDURE GET_FILTERED_EMPLOYEE (
IN_CRITERIA_LIST IN MATCHING_CRITERIA_LIST,
CUR_OUT OUT sys_refcursor
)
AS
OPEN CUR_OUT FOR
--My Select Query--
END;
I am trying to execute SP through C# .NET, and getting error.
var param = new OracleParameter() { ParameterName = "IN_CRITERIA_LIST", Direction = ParameterDirection.Input, CollectionType = OracleCollectionType.PLSQLAssociativeArray, DbType = DbType.Object};
param.Value = /*Some Array */;
var parameters = new List<IDbDataParameter>() {param, new OracleParameter("CUR_OUT", OracleDbType.RefCursor) { Direction = ParameterDirection.Output }};
reader = dbConn.ExecuteReaderWithParams("GET_FILTERED_EMPLOYEE", parameters, CommandType.StoredProcedure);
Error:
Message=Unsupported column datatype
Source=Oracle Data Provider for .NET, Managed Driver
This is not a duplicate of this as I am trying to pass an array of user defined object and not primitive types.
I need to get the value of this stored procedure and pass it as a parameter to another stored procedure.
SqlCommand GetName = new SqlCommand("usp_GetName", sqlcon);
GetName.CommandType = CommandType.StoredProcedure;
GetName.Parameters.AddWithValue("#printer", printerguid);
This stored procedure has a simple select statement that returns only one row at any given point. I need to get that data and pass tat as a parameter elsewhere... Please tell me how to get the value from this stored procedure and store it in a variable
If it only returns one value use this and cast it to the type it is (string, int, etc)
var returnedValue = GetName.ExecuteScalar();
If you have more than 1 fields you should use:
using(IDataReader reader = GetName.ExecuteReader())
{
if (reader.Read())
{
// Populate any object using reader.GetString(reader.GetOrdinal("FieldName"))
// Replace GetString for any data type you need.
}
else
{
// No rows returnes
}
}
CREATE PROCEDURE [dbo].[Code]
#intEpmName NUMERIC,
#strFailedEMPID VARCHAR(1000) output
AS
DECLARE
#FailedCodes VARCHAR(1000)
BEGIN
----
my logic where i need return the value
SET #strFailedEMPID = #FailedCodes
-----
END
In the stored procedure above, I can send the value as "0" to #strFailedEMPID then to my procedure. However, when I return the value from my procedure, then to the same variable #strFailedEMPID I am sending the value as such:
lsqlParam = new SqlParameter("#strFailedEMPID ", SqlDbType.VarChar);
lsqlParam.Value = "0";
lsqlParam.Direction = ParameterDirection.ReturnValue;
lsqlCmd.Parameters.Add(lsqlParam);
Can anyone help with the correct syntax to get the return value from the procedure?
It's because you are defining the parameter in .NET as a ReturnValue which would actually equate to the scenario where you use RETURN within the stored procedure to return an integer (which you're not doing).
Instead, you need to define the #strFailedEMPID parameter as ParameterDirection.Output within your .NET code. If you want to pass a value in AND receive one out through the parameter, use ParameterDirection.InputOutput.
After executing the sproc, you then just:
string value = lsqlCmd.Parameters["#strFailedEMPID"].value;
So....
lsqlParam = new SqlParameter("#strFailedEMPID ", SqlDbType.VarChar);
lsqlParam.Value = "0";
lsqlParam.Direction = ParameterDirection.InputOutput;
lsqlCmd.Parameters.Add(lsqlParam);
lsqlCmd.ExecuteNonQuery();
string value = lsqlCmd.Parameters["#strFailedEMPID"].value;