Определенными пользователя Oracle типы данных (UDT) внутри пакета сопоставления .Чистые пользовательские типы
Я сопоставляю пользовательские типы Oracle .Объем пользовательских типов в Oracle доступ к данным Ассамблеи неуправляемым.
Я следил за этой статьей https://www.codeproject.com/Articles/1261430/Calling-Oracles-Stored-Procedures-and-Mapping-User
Я применил простые сценарии.
1. Создан Оракул определяемый пользователем тип на уровне схемы, т. е.
CREATE OR REPLACE TYPE STUDENT_TYP IS OBJECT ( STUDENT_ID NUMBER, STUDENT_NAME VARCHAR(20), ADDRESS VARCHAR(20), AGE NUMBER, BIRTH_DATE DATE ); CREATE OR REPLACE TYPE STUDENT_TYP_TBL IS TABLE OF STUDENT_TYP;
а вот процедура GET_ALL_STUDENTS body
PROCEDURE GET_ALL_STUDENTS(P_STUDENTS OUT STUDENT_TYP_TBL) AS BEGIN SELECT * BULK COLLECT INTO P_STUDENTS FROM ( SELECT STUDENT_TYP(s.student_id, s.student_name, s.address, s.age, s.birth_date) FROM student s) ; END;
Приведенный выше пример работает нормально. Выше сценарий просто чтобы объяснить нет никаких проблем в реализации
2. Теперь я определил типы внутри пакета, например:
CREATE OR REPLACE PACKAGE STUDENT_PKG AS TYPE PHONE_TYP_RC IS RECORD ( PHONE_ID STUDENT_PHONE.PHONE_ID%TYPE, PHONE_TYPE STUDENT_PHONE.PHONE_TYPE%TYPE, PHONE_NUMBER STUDENT_PHONE.PHONE_NUMBER%TYPE ); TYPE PHONE_RC_TBL IS TABLE OF PHONE_TYP_RC; PROCEDURE GET_ALL_PHONES(P_PHONES_TBL OUT STUDENT_PKG.PHONE_RC_TBL); END;
Ниже приводится тело STUDENT_PKG
create or replace PACKAGE BODY STUDENT_PKG AS PROCEDURE GET_ALL_PHONES(P_PHONES_TBL OUT STUDENT_PKG.PHONE_RC_TBL) IS BEGIN SELECT PH.PHONE_ID, PH.PHONE_TYPE, PH.PHONE_NUMBER BULK COLLECT INTO P_PHONES_TBL FROM STUDENT_PHONE PH; -- END OF GET_ALL_PHONES END; --END OF PACKAGE BODY END;
Когда я добавляю параметр Oracle со всей информацией. Я получил исключение Оракула
"OCI-22303: type \"STUDENT_PKG\".\"PHONE_RC_TBL\" not found"
Я уже определил Пользовательское отображение Oracle с именем STUDENT_PKG.PHONE_RC_TBL
Я уже пробовал со следующими именами
- STUDENT_PKG.PHONE_RC_TBL
- STUDENT_PKG
- PHONE_RC_TBL
Когда я выполняю
OracleCommandBuilder.DeriveParameters(command);
чтобы получить текстовые параметры команды я получаю следующую информациюИмя параметра: P_PHONES_TBL
OracleDbType: Массив
OracleDbTypeEx: Массив
UdtTypeName: KAMI.STUDENT_PKG
DbType: Объект
и когда я выполняю, я получаю следующее исключение
OCI-22303: type "KAMI"."STUDENT_PKG" not found
Это означает, что есть что-то сложное для обработки сопоставления udt пакета .Чистый класс.
Вот мое определение .Чистый пользовательский класс для *P_PHONES_TBL* Parmeter
public abstract class CustomTypeBase<T> : IOracleCustomType, IOracleCustomTypeFactory, INullable where T : CustomTypeBase<T>, new() { private bool _isNull; public bool IsNull { get { return this._isNull; } } public static T Null { get { return new T { _isNull = true }; } } public IOracleCustomType CreateObject() { return new T(); } public abstract void FromCustomObject(OracleConnection con, IntPtr pUdt); public abstract void ToCustomObject(OracleConnection con, IntPtr pUdt); } public abstract class CustomCollectionTypeBase<TType, TValue> : CustomTypeBase<TType>, IOracleArrayTypeFactory where TType : CustomTypeBase<TType>, new() { [OracleArrayMapping()] public TValue[] Values; public override void FromCustomObject(OracleConnection connection, IntPtr pointerUdt) { OracleUdt.SetValue(connection, pointerUdt, 0, Values); } public override void ToCustomObject(OracleConnection connection, IntPtr pointerUdt) { Values = (TValue[])OracleUdt.GetValue(connection, pointerUdt, 0); } public Array CreateArray(int elementCount) { return new TValue[elementCount]; } public Array CreateStatusArray(int elementCount) { return new OracleUdtStatus[elementCount]; } } [OracleCustomTypeMapping("STUDENT_PKG.PHONE_TYP_RC")] public class PhoneRecord : CustomTypeBase<PhoneRecord> { [OracleObjectMapping("PHONE_ID")] public int PhoneId { get; set; } [OracleObjectMapping("PHONE_TYPE")] public string PhoneTYpe { get; set; } [OracleObjectMapping("PHONE_NUMBER")] public string PhoneNumber { get; set; } public override void FromCustomObject(OracleConnection con, IntPtr pUdt) { OracleUdt.SetValue(con, pUdt, "PHONE_ID", PhoneId); OracleUdt.SetValue(con, pUdt, "PHONE_TYPE", PhoneTYpe); OracleUdt.SetValue(con, pUdt, "PHONE_NUMBER", PhoneNumber); } public override void ToCustomObject(OracleConnection con, IntPtr pUdt) { PhoneId = (int)OracleUdt.GetValue(con, pUdt, "PHONE_ID"); PhoneTYpe = OracleUdt.GetValue(con, pUdt, "PHONE_TYPE").ToString(); PhoneNumber = OracleUdt.GetValue(con, pUdt, "PHONE_NUMBER").ToString(); } } [OracleCustomTypeMapping("STUDENT_PKG.PHONE_RC_TBL")] public class PhoneTable : CustomCollectionTypeBase<PhoneTable, PhoneRecord> { }
а вот магазинная процедура вызова
OracleCommand command = new OracleCommand("KAMI.STUDENT_PKG.GET_ALL_PHONES", connection); command.CommandType = System.Data.CommandType.StoredProcedure; try { // OracleCommandBuilder.DeriveParameters(command); OracleParameter param = new OracleParameter() { ParameterName = "P_PHONES_TBL", Direction = System.Data.ParameterDirection.Output, OracleDbType = OracleDbType.Object, OracleDbTypeEx = OracleDbType.Object, UdtTypeName = "STUDENT_PKG.PHONE_RC_TBL", }; command.Parameters.Add(param); command.ExecuteNonQuery(); } catch (Exception ex) { }
Пожалуйста, кто-нибудь испытал то же самое и как решить эту проблему
Что я уже пробовал:
1. я сопоставил UDT уровня схемы с пользовательскими типами, и это сработало для меня
2. Я типы, определенные внутри пакета Oracle и пытался сопоставить с пользовательских типов.
Я получил следующие вопросы.
При добавлении информации о параметрах в команду Oracle возникает ошибка.
"OCI-22303: type \"STUDENT_PKG\".\"PHONE_RC_TBL\" not found"
При использовании
OracleCommandBuilder.DeriveParameters(command);Вот это ошибка
OCI-22303: type "KAMI"."STUDENT_PKG" not found
Я попытался создать OracleCustomTypeMapping со следующими именами
- STUDENT_PKG.PHONE_RC_TBL - STUDENT_PKG - PHONE_RC_TBL