ORM стиль отображения хранимых процедур Oracle с помощью .Net - PullRequest
1 голос
/ 25 августа 2011

Я ищу какой-нибудь инструмент для вызова хранимых процедур Oracle из кода .Net. У нас есть большая устаревшая база данных, которая, честно говоря, немного грязная (без полей идентификаторов, больших составных ключей и дублирующих данных). В настоящее время мы должны осуществлять доступ к данным через хранимые процедуры через пользовательскую библиотеку, которая устарела и содержит ошибки, и я хотел бы заменить ее.

У меня есть некоторый опыт работы с инструментами ORM, такими как nHibernate, но, поэкспериментировав с ним в нашей среде, он, похоже, не самый лучший вариант для работы с устаревшей базой данных, подобной этой.

Кто-нибудь знает хороший инструмент, который позволит легко вызывать хранимые процедуры и отображать результаты в наборы / коллекции объектов? Приятным бонусом будет также возможность обрабатывать транзакции соединений.

Спасибо

Ответы [ 5 ]

2 голосов
/ 25 августа 2011

Новый драйвер Oracle бета-версии Entity Framework позволяет вам сделать это. Вы можете отобразить SP в модель и либо на сущности (если они возвращают эквивалент таблицы), либо создать «сложный тип», который представляет собой класс, построенный на основе того, что возвращает SP.

Я не знаю, сколько СП вам звонят, но для тех, кого я пробовал, это сработало.

Другой вариант - написать собственную библиотеку, которая просто вызывает процедуры и возвращает результаты в виде классов .net, но это потребует от вас много работы по настройке с точки зрения повторяющегося кода (сопоставление параметров с процедурами в Oracle получает утомительно очень быстро).

edit - вот запись файла конфигурации для использования хранимой процедуры, в которой результаты поступают от курсора, являющегося параметром OUT.

  <oracle.dataaccess.client>
    <settings>
      <add name="ENVMSTR.P_ORG_UNIT_R_BY_STAFF.RefCursor.RESULT_CURSOR_P" value="implicitRefCursor bindinfo='mode=Output'" />
    </settings>
  </oracle.dataaccess.client>

edit 2 - И хранимая процедура в вопросе:

create or replace
PROCEDURE                 P_ORG_UNIT_R_BY_STAFF 
(
  STAFF_ID_P IN NUMBER
, RESULT_CURSOR_P OUT SYS_REFCURSOR  
) AS 
BEGIN
  OPEN RESULT_CURSOR_P FOR
    select *
      from dept_organizational_unit
      start with deptorgunit_cd = (select deptorgunit_cd from staff where staff_id = STAFF_ID_P)
      connect by prior deptorgunit_parent_cd = deptorgunit_cd;
END P_ORG_UNIT_R_BY_STAFF;
1 голос
/ 25 августа 2011

Если вам нужна только обработка SPROC с параметризацией и материализацией (данные в объекты), dapper-dot-net прост, минималистичен и прекрасно работает в Oracle; например:

var user = cnn.Query<User>("spGetUser", new {Id = 1}, 
    commandType: CommandType.StoredProcedure).First();

пункты:

  • spGetUser - это имя sproc
  • он вызывается как sproc через commandType
  • параметры выводятся из переданного объекта; в этом случае предполагается, что существует параметр с именем Id, который принимает целое число со значением 1, переданным в
  • применяется прямая карта столбца к свойству, создающая объект User для каждой возвращаемой строки
  • в этом случае мы также используем LINQ-to-Objects, чтобы проиллюстрировать чтение 1 строки просто

обратите внимание, что также поддерживается отображение нескольких сеток данных и горизонтальное разбиение (на разные объекты в связанном графике).

1 голос
/ 25 августа 2011

ЕСЛИ коммерческая библиотека - это вариант, которым мы действительно довольны Devart (см. http://www.devart.com/dotconnect/oracle/features.html)..., они поддерживают LINQ и PLINQ и EF и хранимые процедуры, курсоры REF и т. Д. - от Oracle 7.3 до 11g / .NET 2 и up / 32 + 64 бит ...

Не связан, просто счастливый клиент ...

0 голосов
/ 03 января 2012

Вам лучше использовать генератор кода для слоя доступа к данным. Писать это довольно просто. Может генерировать даже CRUD PL / SQL.

Вот небольшой пример:

Private Sub GeneraCapaAccesoDato(ByVal tipo As Integer, ByVal modo As String)
    Dim sb As New StringBuilder()
    Dim Tabla As String = lbTabla.SelectedValue
    Dim dt As DataTable = RecuperarDatosTabla(Tabla)
    sb.Append(String.Format("public int {1}(OracleConnection con, BE{0} oBE{0})", Tabla, modo))
    sb.AppendLine("{")
    sb.AppendLine("int Resultado;")
    sb.AppendLine(String.Format("OracleCommand cmd = new OracleCommand(""Pa_{0}_{1}"", con);", Tabla, modo))
    sb.AppendLine("cmd.CommandType = CommandType.StoredProcedure;")
    sb.AppendLine("")
    Dim i As Integer
    Row = dt.Select()
    Dim NomTabla As String
    Dim Tamaño As Integer
    Dim scala As Integer
    Dim TipoDato As String = "Ninguno"
    Dim precision As Integer
    Dim aux As Object
    Dim aux1 As Object
    Dim llave As Integer
    For i = tipo To Row.Count() - 1
        llave = Int32.Parse(Row(i).Item(7))
        NomTabla = Row(i).Item(0).ToString()
        Tamaño = Integer.Parse(Row(i).Item(2).ToString())
        aux = Row(i).Item(4).ToString()
        scala = Integer.Parse(If(aux = "", 0, aux))

        aux1 = Row(i).Item(3).ToString()
        precision = Integer.Parse(If(aux1 = "", 0, aux1))

        If scala > 0 Then
            If scala >= 0 And scala <= 15 Then
                TipoDato = "OracleDbType.Double"
            End If
        ElseIf Row(i).Item(1).ToString() = "NUMBER" Then
            If precision < 2 Then
                TipoDato = "OracleDbType.Int16"
            ElseIf precision >= 2 And precision <= 9 Then
                TipoDato = "OracleDbType.Int32"
            ElseIf precision >= 10 And precision <= 18 Then
                TipoDato = "OracleDbType.Int64"
            End If
        Else
            If Row(i).Item(1).ToString() = "DATE" Then
                TipoDato = "OracleDbType.Date "
            End If
            If Row(i).Item(1).ToString() = "VARCHAR2" Then
                TipoDato = "OracleDbType.Varchar2  "
            End If
            If Row(i).Item(1).ToString() = "CHAR" Then
                TipoDato = "OracleDbType.Char "
            End If

        End If
        sb.AppendLine(String.Format("OracleParameter Par{1} = cmd.Parameters.Add(""P_{0}"",{2});", _
                                    NomTabla, If(tipo = 0, i + 1, i), TipoDato))

        If Row(i).Item(1).ToString() = "VARCHAR2" Or Row(i).Item(1).ToString() = "CHAR" Then
            sb.AppendLine(String.Format("Par{1}.Size = {0};", Tamaño, If(tipo = 0, i + 1, i)))
        End If

        sb.AppendLine(String.Format("Par{0}.Direction = ParameterDirection.Input;", If(tipo = 0, i + 1, i)))
        sb.AppendLine(String.Format("Par{0}.Value = oBE{2}.{1};", If(tipo = 0, i + 1, i), NomTabla, Tabla))
        sb.AppendLine("")
        TipoDato = ""

    Next
    sb.AppendLine("Resultado = cmd.ExecuteNonQuery();")
    sb.AppendLine("return Resultado;")
    sb.AppendLine("}")
    rtbVisor.Text = sb.ToString()
End Sub
Private Function RecuperarDatosTabla(ByVal NombreTabla As String) As DataTable
    sb = New StringBuilder
    sb.Append(" select COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, NULLABLE, DATA_DEFAULT ,column_id")
    sb.Append(" from(USER_TAB_COLUMNS)")
    sb.Append(String.Format(" where TABLE_NAME = '{0}' order by table_name,column_id ", NombreTabla))
    Using con As New OracleConnection(strConexion)
        con.Open()
        dt = New DataTable
        Dim da As OracleDataAdapter = New OracleDataAdapter(sb.ToString(), con)
        da.Fill(dt)
    End Using
    Return dt
End Function
0 голосов
/ 09 декабря 2011

Для тех из вас, кто пытается заставить импорт функций Entity Framework работать с Oracle, вот пошаговое руководство, которое вы можете использовать: http://www.oracle.com/webfolder/technetwork/tutorials/obe/db/dotnet/EntityFrameworkOBE/EntityFrameworkOBE.htm

Есть еще одна статья в журнале, в которую я написал статью, в которую входит: http://www.oracle.com/technetwork/issue-archive/2011/11-sep/o51odt-453447.html

Примечание. Во время этой публикации эти обходы не работали из-за некоторых изменений в ключевых словах app.config, которые произошли в бета-версии 3. См. Файл readme в каталоге ODP.NET бета-версии.

Ключевые слова, которые были изменены и влияющие на ходьбу, можно изменить следующим образом:

NATIVE_DATA_TYPE - NATIVEDATATYPE

и

PROVIDER_DB_TYPE до PROVIDERDBTYPE

См. Файл readme в каталоге ODT для дополнительных предостережений относительно этого. В (будущем) производственном выпуске (недоступном на момент публикации) в онлайн-справке Oracle Developer Tools for Visual Studio есть раздел «Использование Entity Framework». Этот раздел содержит предостережения о сопоставлении с хранимыми процедурами и функциями. Пожалуйста, прочтите эту документацию.

Подробнее о формате метаданных app.config см. В интерактивной справке ODP.NET в разделе «Поддержка неявного связывания REF CURSOR».

Обратите внимание, что эти подробные метаданные app.config нужны только в том случае, если в результате вы отображаете сложный тип. Вам это не понадобится, если вы вернете сущность.

К сожалению, процесс изменения app.config таит в себе возможность совершать ошибки. Любая ошибка приведет к тому, что кнопка «Получить информацию о столбце» в мастере функции импорта ничего не сделает. Мы знаем об этом и планируем инструмент конфигурации в будущем выпуске.

Кристиан Шей

Oracle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...