Прежде чем я начну, я советую вам сделать глубокий вдох и понять, что это очень длинный вопрос и в нем было 3-4 проблемы в одном контексте. Так что наберитесь терпения при чтении. (напишите в комментарии, если вам что-то нужно, образец кода или что-то еще, поскольку я серьезно ищу решение).
Недавно я работал с клиентом, и он хотел иметь базу данных приложений в Oracle. Приложение было построено на ASP.NET MVC.
Мы выбрали Oracle 11g express в качестве среды разработки, и клиент подтвердил то же самое. Мы решили использовать ODAC 32bit .NET Provider который поддерживает ORM (EF). Сначала мы провели пробный пример реализации операции CRUD, и все работало нормально. Затем мы начали разработку реальных требований клиента. Через 2-3 месяца товар был готов к отправке. Так что до сих пор в ASP.NET и Oracle 11g все работало нормально. Когда мы приступили к развертыванию и UAT, мы узнали, что у клиента есть Oracle 9i для его существующей ERP, которая не соответствует версии, которую мы разработали. Поэтому мы провели поиск в Интернете, чтобы проверить, совместим ли тот же поставщик ODAC с Oracle 9i. Мы нашли ссылки, где упоминалось, что он совместим с Oracle 9i.
Мы только что перенесли базу данных на сервер Oracle 9i, соответствующим образом изменили модель EF и обнаружили следующие проблемы:
1. Транзакция не была совершена автоматически!
using (TransactionScope transaction = new TransactionScope())
{
// some code written here
}
Тот же код работал с 11g, а при переносе на Oracle 9i он перестал работать. Транзакции не фиксировались автоматически после завершения оператора using. Мы намеренно написали transaction.commit();
в блоке using, и он заработал.
Это ожидаемое поведение?
2. Проблема с VARCHAR2
типом данных и поставщиком ODP NET. Мы создали несколько хранимых процедур в базе данных с Varchar2
и другими типами базы данных в качестве параметра. При доступе к этой хранимой процедуре с использованием стиля ADO.NET (OracleConnection, OracleCommand и OracleParameter) мы узнали, что параметры, имеющие тип данных VARCHAR2
, иногда усекают данные, даже если данные, переданные в параметр, имеют размер меньше, чем заданный столбец таблицы. Он просто случайным образом удаляет количество символов с конца. Проблема также регистрируется здесь, на форуме Oracle
Мы не смогли решить эту проблему.
3. Ограничение размера встроенного запроса (количество символов). Для решения проблемы, упомянутой в пункте 2, мы поняли, что должны преобразовать эту хранимую процедуру во встроенный запрос и вызывать те, которые используют ADO.NET (старый стиль в школьные годы кодирование)! Мы преобразовали все наши хранимые процедуры в строковые сценарии и написали следующее:
OracleCommand command=new OracleCommand("Select * from something",Connection);
И использовал ту же технику для других операторов DML. Теперь все заработало, провели UAT и сделали приложение работающим. Через 10-15 дней мы обнаружили странную проблему. Если запрос (встроенный запрос) имеет размер более 4000 символов, то сервер Oracle выдает исключение, в котором говорится, что «Запрос слишком длинный для выполнения» (я не помню точно исключение или сообщение, но оно было похоже на то, что я написал) . Мы взяли образцы данных в среде разработки и отладили код и узнали, что размер SQL-запроса слишком длинный, от 32000 до 64000 символов! Мы знали, что решение этой проблемы было тем же: «Если бы мы могли каким-то образом правильно вызывать хранимые процедуры!» Но мы не можем, потому что у нас нет выбора.
В качестве решения мы воссоздали эти хранимые процедуры в базе данных и вызвали их встроенными!
OracleCommand command=new OracleCommand("BEGIN ProceduretoCall(Param1,Param2); END;",Connection);
И с тех пор работает.
Помня о вышеуказанных проблемах,
- Я не могу вызвать хранимую процедуру из ASP.NET обычным способом (CommandType.StoredProcedure) # проблема-1 выше
- Я не могу вернуть какие-либо данные, скалярное значение или возвращаемое значение из хранимой процедуры после вставки или обновления. # проблема-3 выше
- Я не могу использовать транзакцию на уровне кода. (Он постоянно говорит, что инициализируется распределенная транзакция, но на самом деле у меня вообще нет распределенной транзакции!)
Почему все вышеперечисленное в конце после Go Live? Это был почти кошмар проблем с Oracle, которые я решал в течение месяца, одну за другой, и это заставило меня задуматься
Действительно ли инструмент ODP.NET/ ODAC надежен?
Если нет, то какой еще вариант я могу выбрать, исходя из вашего опыта? (Пожалуйста, знайте, что ODBC также имеет аналогичную проблему с Oracle 9i).
Я, скорее всего, поработаю над подобным проектом на следующей неделе, и я подумал, что на этот раз я хочу быть готовым с лучшим подходом.