2012-04-18 10 views
8

This answer için this question iyi, ancak bir Oracle yordamına bir dizi veya tablo göndermek ve sonra bu tabloyu yordamda kullanmak için ADO.NET kodunu arıyorum. SQL Server tablo değerli parametrelerADO.NET/C# ile Dizilim/Tablo Parametresini Oracle'a (ODP.NET 10g) nasıl kullanılır?

, oldukça basittir:

CREATE TYPE [dbo].[IntTable] AS TABLE(
    [intvalue] [int] NOT NULL, 
    PRIMARY KEY CLUSTERED 
    (
     [intvalue] ASC 
    )WITH (IGNORE_DUP_KEY = OFF) 
) 
GO 

CREATE PROCEDURE dbo.UseTable 
    @SomeInt INT 
    ,@IntTable dbo.IntTable READONLY 
AS 
BEGIN 
    -- Do whatever using @SomeInt and @IntTable like: 
    INSERT INTO Assignments (masterid, childid) 
    SELECT @SomeInt, intvalue 
    FROM @IntTable 
END 
GO 

Sonra istemci üzerinde:

CREATE OR REPLACE TYPE TRAIT_ID_TABLE AS TABLE OF NUMBER; 

PROCEDURE SET_TRAITS(P_CUST_TANK_PROD_ID IN CUST_TANK_PROD.CUST_TANK_PROD_ID%TYPE, P_TRAIT_IDS IN TRAIT_ID_TABLE) 
AS 
BEGIN 
    DELETE FROM TANK_TRAIT 
     WHERE CUST_TANK_PROD_ID = P_CUST_TANK_PROD_ID; 

    INSERT INTO TANK_TRAIT(CUST_TANK_PROD_ID, TRAIT_ID) 
    SELECT P_CUST_TANK_PROD_ID, COLUMN_VALUE FROM TABLE(P_TRAIT_IDS); 

    COMMIT; 
EXCEPTION 
    WHEN OTHERS 
    THEN 
    ROLLBACK; 
END; 


var param = new OracleParameter(); 
param.ParameterName = "P_TRAIT_IDS"; 
param.OracleDbType = OracleDbType.Decimal; 
param.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
param.Direction = ParameterDirection.Input; 
param.Value = traitIdList.ToArray<int>(); 
param.Size = traitIdList.Count; 
cmd.Parameters.Add(param); 

Ve:

var param = new List<int>(); 
param.Add(1); 
param.Add(2); 

Cm.Parameters 
    .AddWithValue("@IntTable", param /* IEnumerable<Int> */) 
    .SqlDbType = SqlDbType.Structured 

Bu şu anda ne var Bunu ExecuteNonQuery'de alıyorum:

System.AccessViolationException was caught 
    Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
    Source=Oracle.DataAccess 
    StackTrace: 
     at Oracle.DataAccess.Client.OpsSql.ExecuteNonQuery(IntPtr opsConCtx, IntPtr& opsErrCtx, IntPtr& opsSqlCtx, IntPtr& opsDacCtx, IntPtr opsSubscrCtx, Int32& isSubscrRegistered, OpoSqlValCtx*& pOpoSqlValCtx, OpoSqlRefCtx& pOpoSqlRefCtx, IntPtr[] pOpoPrmValCtx, OpoPrmRefCtx[] pOpoPrmRefCtx, OpoMetValCtx*& pOpoMetValCtx, Int32 prmCnt) 
     at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery() 
     at EDC2.Domain.TraitList.SaveTraits(String connectionString) in C:\code\EDC2\trunk\app\EDC2.Domain\Trait.cs:line 195 
    InnerException: 
+1

bakınız:

CREATE OR REPLACE package SOME_PACKAGE as ... type t_number_tab is table of number index by pls_integer; ... procedure ins_test(i_id_tab in t_number_tab, o_inserted out number); end SOME_PACKAGE; CREATE OR REPLACE package body SOME_PACKAGE as procedure ins_test(i_id_tab in t_number_tab, o_inserted out number) is begin -- inserts all records to test table based on incoming table of ids forall i in i_id_tab.first .. i_id_tab.last insert into TEST_TAB (id, val1, val2) select id,val1,val2 from main_tab where id = i_id_tab(i); o_inserted := SQL%ROWCOUNT; commit; exception when others then rollback; raise; end ins_test; ... end SOME_PACKAGE; 

Ardından C# kodu gibi görünecektir http://stackoverflow.com/questions/5557318/can-an-oracle-stored-procedure-that-has-a-nested-table-parameter-be-called-from – Eggi

+0

@Eggi Ne yazık ki bu teknik ile çalışmaz 10g clie nt ve 11g istemci ve 10g istemci çalışmasında .NET (veya 11g istemci üzerinde çalışan tüm bunları denemek için onları almak için) karıştırmak için çalışıyorum uyumsuz sağlayıcı hataları ve yapıcı intialization sorunları ile bana uyuyor. –

cevap

18

Bu ODP.NET için çalışır (odac):

Oracle paketi olacak kurulum gibi:

string connStr = "User Id=xxx;Password=xxxx;Data Source=xxxxx;"; 
OracleConnection _conn = new OracleConnection(connStr); 
_conn.Open(); 

OracleCommand cmd = _conn.CreateCommand(); 
cmd.CommandText = "some_package.ins_test"; 
cmd.CommandType = CommandType.StoredProcedure; 

OracleParameter p1 = new OracleParameter(); 
OracleParameter p2 = new OracleParameter(); 

p1.OracleDbType = OracleDbType.Decimal; 
p1.Direction = ParameterDirection.Input; 
p2.OracleDbType = OracleDbType.Decimal; 
p2.Direction = ParameterDirection.Output; 

p1.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
p1.Value = new int[3] { 1, 2, 3 }; 
p1.Size = 3; 

cmd.Parameters.Add(p1); 
cmd.Parameters.Add(p2); 

cmd.ExecuteNonQuery(); 
+0

Teşekkürler - Ben sadece geliştirme 11g müşteri ile çalışan UDT yöntemi yerine çalışıyorum. Ancak, System.AccessViolationException –

+0

wow'u alıyorum, yönetilmeyen kod kullanıyor musunuz? – tbone

+0

nope, yönetilen kod yok –