Tôi cần trợ giúp tìm hiểu xem cách tôi đang cố gắng sử dụng một con trỏ Ref là một tham số ReturnValue cho nhiều bản ghi/giá trị, với PL/SQL chỉ là CommandText của đối tượng OracleCommand chứ không phải trong một thủ tục hoặc hàm được lưu trữ, thậm chí có thể. Nếu điều đó là không thể, những gì tôi đang cố gắng làm là tìm cách phát hành một câu lệnh PL/SQL sẽ cập nhật một số lượng bản ghi chưa biết (phụ thuộc vào số lượng khớp với mệnh đề WHERE) và trả về Các id của tất cả các bản ghi Cập nhật trong một OracleDataReader, sử dụng một vòng chuyến đi duy nhất tới cơ sở dữ liệu, mà không sử dụng một thủ tục hoặc hàm được lưu trữ.Làm thế nào để sử dụng một Oracle Ref Cursor từ C# ODP.NET như một tham số ReturnValue, mà không cần sử dụng một chức năng được lưu trữ hoặc thủ tục?
Tôi đang làm việc với Oracle 11g sử dụng ODP.NET để liên lạc với cơ sở mã C# .NET 4.0 hiện có sử dụng kết nối SQL để truy xuất/sửa đổi dữ liệu. Định nghĩa đơn giản hóa bảng thử nghiệm Tôi đang sử dụng trông giống như vậy:
CREATE TABLE WorkerStatus
(
Id NUMERIC(38) NOT NULL
,StateId NUMERIC(38) NOT NULL
,StateReasonId NUMERIC(38) NOT NULL
,CONSTRAINT PK_WorkerStatus PRIMARY KEY (Id)
)
tôi Pre-cư bảng với ba giá trị thử nghiệm như vậy:
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (1, 0, 0)';
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (2, 0, 0)';
EXECUTE IMMEDIATE 'INSERT INTO WorkerStatus (Id, StateId, StateReasonId)
VALUES (3, 0, 0)';
END;
các câu lệnh SQL hiện có, nạp từ một tập tin script tên Oracle_UpdateWorkerStatus2, và chứa trong OracleCommand.CommandText trông giống như vậy:
DECLARE
TYPE id_array IS TABLE OF WorkerStatus.Id%TYPE INDEX BY PLS_INTEGER;
t_ids id_array;
BEGIN
UPDATE WorkerStatus
SET
StateId = :StateId
,StateReasonId = :StateReasonId
WHERE
StateId = :CurrentStateId
RETURNING Id BULK COLLECT INTO t_Ids;
SELECT Id FROM t_Ids;
END;
tôi đã tạo ra một chương trình thử nghiệm # C nhỏ để cố gắng cô lập nơi tôi nhận được một O RA-01.036 "bất hợp pháp biến tên/số" lỗi mà có một cơ thể chính mà trông giống như vậy:
using System;
using System.Configuration;
using System.Data;
using System.Text;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
namespace OracleDbTest
{
class Program
{
static void Main(string[] args)
{
// Load the SQL command from the script file.
StringBuilder sql = new StringBuilder();
sql.Append(Properties.Resources.Oracle_UpdateWorkerStatus2);
// Build and excute the command.
OracleConnection cn = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleSystemConnection"].ConnectionString);
using (OracleCommand cmd = new OracleCommand(sql.ToString(), cn))
{
cmd.BindByName = true;
cn.Open();
OracleParameter UpdatedRecords = new OracleParameter();
UpdatedRecords.OracleDbType = OracleDbType.RefCursor;
UpdatedRecords.Direction = ParameterDirection.ReturnValue;
UpdatedRecords.ParameterName = "rcursor";
OracleParameter StateId = new OracleParameter();
StateId.OracleDbType = OracleDbType.Int32;
StateId.Value = 1;
StateId.ParameterName = "StateId";
OracleParameter StateReasonId = new OracleParameter();
StateReasonId.OracleDbType = OracleDbType.Int32;
StateReasonId.Value = 1;
StateReasonId.ParameterName = "StateReasonId";
OracleParameter CurrentStateId = new OracleParameter();
CurrentStateId.OracleDbType = OracleDbType.Int32;
CurrentStateId.Value = 0;
CurrentStateId.ParameterName = "CurrentStateId";
cmd.Parameters.Add(UpdatedRecords);
cmd.Parameters.Add(StateId);
cmd.Parameters.Add(StateReasonId);
cmd.Parameters.Add(CurrentStateId);
try
{
cmd.ExecuteNonQuery();
OracleDataReader dr = ((OracleRefCursor)UpdatedRecords.Value).GetDataReader();
while (dr.Read())
{
Console.WriteLine("{0} affected.", dr.GetValue(0));
}
dr.Close();
}
catch (OracleException e)
{
foreach (OracleError err in e.Errors)
{
Console.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
System.Diagnostics.Debug.WriteLine("Message:\n{0}\nSource:\n{1}\n", err.Message, err.Source);
}
}
cn.Close();
}
Console.WriteLine("Press Any Key To Exit.\n");
Console.ReadKey(false);
}
}
}
tôi đã cố gắng thay đổi tên tham số, đặt tên và không đặt tên các tham số UpdatedRecords, thay đổi thứ tự để UpdateRecords là lần đầu tiên hoặc cuối cùng. Điều gần nhất tôi đã tìm thấy cho đến nay là câu hỏi StackOverflow sau đây (How to call an Oracle function with a Ref Cursor as Out-parameter from C#?), nhưng vẫn sử dụng một chức năng được lưu trữ như xa như tôi có thể nói.
Chạy kịch bản Oracle_UpdateWorkerStatus2 PL/SQL từ SQL Developer, nó sẽ mở ra "Enter liên kết" hộp thoại nơi tôi nhập các giá trị cho CurentStateId, StateId và StateReasonId như trong đoạn mã trên, nhưng nó mang lại cho các báo cáo lỗi sau:
Error report:
ORA-06550: line 13, column 17:
PL/SQL: ORA-00942: table or view does not exist
ORA-06550: line 13, column 2:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Tôi thực sự không hiểu tại sao nó cho tôi biết bảng không tồn tại, khi tôi đã định nghĩa bảng WorkerStatus và khai báo biến t_Ids, kiểu id_array, cũng là một bảng. Bất kỳ trợ giúp ở đây được đánh giá cao.
Đây có phải là vấn đề về đặc quyền/khả năng hiển thị không? Khi bạn kết nối thủ công với tài khoản oracle, bạn đã thực thi kịch bản lệnh "Oracle_UpdateWorkerStatus2", bạn có thể chọn từ bảng workerstatus không? –
Tôi có thể chọn từ bảng WorkerStatus, cũng như thả và tạo nó. Tôi khá mới với Oracle, vì vậy tôi không biết liệu có bất kỳ đặc quyền nào đặc biệt tôi cần để sử dụng các con trỏ không, nhưng kỹ thuật viên IT/DBA của chúng tôi đã thiết lập tất cả các đặc quyền mà các nhà phát triển của chúng tôi thường sử dụng, vì vậy tôi không tin đây là vấn đề đặc quyền. Tôi sẽ hỏi anh ta vào thứ hai mặc dù. – Paul
Đã kiểm tra với DBA của chúng tôi và anh ấy không biết bất kỳ đặc quyền đặc biệt nào được yêu cầu để làm những gì tôi đang cố gắng. Ngoài ra, ông đã nhanh chóng quét những gì tôi đã có ở đây, và không thấy bất kỳ lý do tại sao nó không hoạt động. Bất kỳ suy nghĩ về những gì tôi có thể làm sai, hoặc một cách khác để đạt được các mục tiêu? – Paul