Действительно ли параметр курсора должен быть объявлен иначе, чем обычный параметр?

Хорошо, кажется, никто не знает, как решить проблему, которую я зацикливаю на наборе курсора/результата для хранения в списке, поэтому я собираюсь разбить его на части и попытаться пройти через него таким образом. Итак, прежде всего:

Я добавляю параметры SQL к объекту OracleCommand таким образом (отлично работает):

cmd.Parameters.Add("ABCID", _ABCID);
cmd.Parameters["ABCID"].Direction = ParameterDirection.Input;
cmd.Parameters["ABCID"].DbType = DbType.String;

IOW, когда я добавляю параметр, я передаю имя параметризованной части SQL ("ABCID" выше) и значение, чтобы дать ему (_ABCID - это переменная, которой было присвоено, скажем, "42").

Однако при добавлении параметра Cursor (output) кажется, что требуется не значение (например, инициализированный объект курсора), а просто тип данных:

cmd.Parameters.Add("cur", Devart.Data.Oracle.OracleDbType.Cursor);
cmd.Parameters["cur"].Direction = ParameterDirection.Output;

(Я пробовал оба способа, и ни один из них не работает, так что...?)

Действительно/таким образом, мой вопрос: действительно ли это правильный способ объявления параметра Cursor для вывода обратно для обхода/доступа?

Я использую новую версию компонентов DevArt DotConnect (6.80.332), VS 2010, .NET 4.

Обновлено:

Вот код в большем контексте:

public void PopulateCurrentUserRoles(String AUserName, List<String> ACurrentUserRoles) { 
  _UserName = AUserName; 

  String query = "select roleid from ABCrole where ABCid = :ABCID"; 
  Devart.Data.Oracle.OracleCommand cmd = new Devart.Data.Oracle.OracleCommand(query, con); 
  cmd.CommandType = CommandType.Text; 
  int _ABCID = GetABCIDForUserName(); 

  cmd.Parameters.Add("cur", Devart.Data.Oracle.OracleDbType.Cursor); 
  cmd.Parameters["cur"].Direction = ParameterDirection.Output; 

  cmd.Parameters.Add("ABCID", _ABCID); 
  cmd.Parameters["ABCID"].Direction = ParameterDirection.Input; 
  cmd.Parameters["ABCID"].DbType = DbType.String; 
  //cmd.ExecuteNonQuery(); blows up: "illegal variable name/number" 
  //cmd.ExecuteCursor();   " " 
  //cmd.ExecuteReader();   " " 
  Devart.Data.Oracle.OracleCursor oraCursor = 
    (Devart.Data.Oracle.OracleCursor)cmd.Parameters["cur"].Value; 
  Devart.Data.Oracle.OracleDataReader odr = oraCursor.GetDataReader(); // "Object reference not set to an instance of an object" 
  while (odr.Read()) { 
    ACurrentUserRoles.Add(odr.GetString(0)); 
  } 
}

person B. Clay Shannon    schedule 29.03.2012    source источник
comment
Почему вы используете курсор? Курсоры - это (как правило) худшее, что вы можете сделать в SQL? Я предлагаю пересмотреть SQL AND/OR, используя цикл WHILE. Помните, что SQL основан на логике SET, а не процедурной. Если вы сильно зацикливаетесь, вы должны делать это в своем коде, а не в SQL.   -  person Justin Pihony    schedule 29.03.2012
comment
ни один из них не работает, на самом деле не объясняет то, что вы наблюдали, когда пробовали это...   -  person Jon Skeet    schedule 29.03.2012
comment
@Jon: Если я вызову ExecuteNonQuery() - что кажется консенсусом, хотя для меня это не имеет смысла, поскольку мои операторы SQL ЯВЛЯЮТСЯ запросом (выбрать) - я получаю недопустимое имя/номер переменной. Если я прокомментирую ExecuteNonQuery(), я получу ссылку на объект, не установленную на экземпляр объекта, когда я вызываю GetDataReader()   -  person B. Clay Shannon    schedule 29.03.2012
comment
@Justin: я пытаюсь использовать цикл while, и именно это я делал с компонентами Oracle ODP. Я не понимаю, как это сделать с компонентами DotConnect.   -  person B. Clay Shannon    schedule 29.03.2012
comment
@Justin: Мой SQL - это простой выбор с параметром. Я хочу пройтись по результирующему набору, назначая то, что возвращает SQL, членам списка строк.   -  person B. Clay Shannon    schedule 29.03.2012
comment
@ClayShannon: вы не показали код, который вызывает GetDataReader, из-за чего трудно сказать, что происходит...   -  person Jon Skeet    schedule 29.03.2012
comment
Я добавлю приведенный выше код в обновленный раздел.   -  person B. Clay Shannon    schedule 30.03.2012


Ответы (2)


следующее взято из Руководства разработчика поставщика данных Oracle для .NET. да, я знаю, "Деварт". Тем не менее, он предлагает следующее:

  • Будьте осторожны с объявлением ввода параметров.
  • добавьте этот параметр курсора/вывода в коллекцию Parameters перед любыми другими.

В общем... мой гид показывает OracleDbType.RefCursor, но не OracleDbType.Cursor. Если у DevArt есть RefCursor, попробуйте его. В Visual Studio, какой тип .NET считает этим параметром? Этот вопрос не такой глупый, как я привык думать.

... С другой стороны, если параметр задан как тип OracleDbType.Char путем установки свойства OracleDbType, выходные данные возвращаются как тип OracleString. Если оба свойства DbType и OracleDbType установлены перед выполнением команды, вступает в силу последний параметр.

. . .

«Приложение не должно привязывать значение для выходных параметров; ODP.NET несет ответственность за создание объекта значения и заполнение свойства OracleParameter Value объектом. При привязке по положению (по умолчанию) к функции ODP.NET ожидает возвращаемое значение должно быть привязано первым, перед любыми другими параметрами».


ИЗМЕНИТЬ:

Основываясь на самоответе @Clay... поэтому для вывода не указан параметр, а просто делается это: OracleDataReader odr = cmd.ExecuteReader();

person radarbob    schedule 29.03.2012
comment
Будьте осторожны с объявлением ввода параметров - что означает...? - person B. Clay Shannon; 29.03.2012
comment
Ref есть, но нет RefCursor. Замена .Cursor на .Ref не имела значения (то же сообщение об ошибке). - person B. Clay Shannon; 29.03.2012
comment
Примеры DotConnect, которые я видел, касаются использования DataAdapter, его заполнения и последующего предоставления сетки с этими данными. Я начинаю думать, что мне придется сделать что-то подобное, а затем пройтись по набору данных (какой посредник мне не нужен), чтобы заполнить мой список строк... ааааа - person B. Clay Shannon; 30.03.2012

Прямо из первых уст (люди DevArt):

_UserName = AUserName;
// From the DevArtisans:
String query = "select roleid from ABCrole where ABCid = :ABCID";
Devart.Data.Oracle.OracleCommand cmd = new Devart.Data.Oracle.OracleCommand(query, con);
cmd.CommandType = CommandType.Text;
int _ABCID = GetABCIDForUserName();
cmd.Parameters.Add("ABCID", _ABCID);
cmd.Parameters["ABCID"].Direction = ParameterDirection.Input;
cmd.Parameters["ABCID"].DbType = DbType.String;
Devart.Data.Oracle.OracleDataReader odr = cmd.ExecuteReader();
while (odr.Read()) {
  ACurrentUserRoles.Add(odr.GetString(0));
}

Цитируя Кейси и Sonshine Banned: «Вот так, угу, угу, мне это нравится, угу, угу»; на самом деле, я терпеть не могу это дерьмо, но прямо сейчас я отношусь к этому чувству.

person B. Clay Shannon    schedule 30.03.2012