Как мне сопоставить Oracle UDT с ODP.NET без использования OracleObjectMappingAttribute? - PullRequest
9 голосов
/ 01 октября 2009

Уровень доступа к данным в нашем приложении будет использовать функциональность UDT Oracle. Мы будем только передавать объекты UDT в базу данных и из нее.

На данный момент мы генерируем пользовательские классы, используя функцию, поставляемую с ODP.NET (которая создает действительно ужасно выглядящий класс, который нам действительно не нужен в нашей кодовой базе).

Затем мы используем отдельный класс отображения для сопоставления пользовательского класса с одним из наших бизнес-объектов (и обратно при сохранении).

Я пытаюсь найти лучший способ сделать это.

Я думал, что просто покончу с сгенерированными классами и напишу класс отображения, который реализует IOracleCustomType. Методы From / ToCustomObject будут затем отображаться из моего UDT в мои бизнес-объекты. Однако, это вызвало у меня проблемы, когда я попробовал это - я получил ошибку «Атрибут объекта не сопоставлен с элементом пользовательского типа». Похоже, что для двух методов мне также нужны атрибуты в моем классе отображения - по одному атрибуту для каждого элемента в UDT.

Например - рабочий процесс UDT содержит три элемента - статус, время создания и созданный. Мой UDT хорош и прост:

TYPE workflow_type AS OBJECT
(status                                  VARCHAR2(8)
,created_by                              VARCHAR2(30)
,created_datetime            DATE
);

Как и бизнес-объект, в котором я хочу оказаться:

public class Workflow
{
    /// <summary>
    /// Gets the status of the workflow.
    /// </summary>
    /// <value>The status.</value>
    public string Status { get; private set; }

    /// <summary>
    /// Gets the Windows Logon Id of the user performing the action
    /// </summary>
    public string CreatedBy{ get; private set; }
    /// <summary>
    /// Gets the time of the action 
    /// </summary>
    public DateTime CreatedTime { get; private set; }
}

Я хочу перейти от одного к другому, не добавляя код Oracle в бизнес-объект.

Поэтому я подумал о создании класса отображения, подобного этому:

public class WorkFlowMapper : IOracleCustomType
{
    public BusinessObjects.WorkFlow BusinessObject {get; private set;}

    public WorkFlowMapper(BusinessObjects.WorkFlow businessObject)
    {
        BusinessObject = businessObject;
    }

    public WorkFlowMapper(){}

    public void FromCustomObject(OracleConnection con, IntPtr pUdt)
    {
        OracleUdt.SetValue(con, pUdt, "STATUS", BusinessObject.Status);
        OracleUdt.SetValue(con, pUdt, "CREATED_BY", BusinessObject.CreatedBy);
        OracleUdt.SetValue(con, pUdt, "CREATED_DATETIME", BusinessObject.CreatedTime);
    }

    public void ToCustomObject(OracleConnection con, IntPtr pUdt)
    {

        BusinessObject = new BusinessObjects.WorkFlow(
            (string)OracleUdt.GetValue(con, pUdt, "STATUS"),
            (string)OracleUdt.GetValue(con, pUdt, "CREATED_BY"),
            (string)OracleUdt.GetValue(con, pUdt, "CREATED_DATETIME")
        );
    }
}

// Factory to create an object for the above class
[OracleCustomTypeMappingAttribute("MYUSER.WORKFLOW_TYPE")]
public class CurrencyExposureFactory : IOracleCustomTypeFactory
{

    public virtual IOracleCustomType CreateObject()
    {
        WorkFlowMapper obj = new WorkFlowMapper();
        return obj;
    }
}

Но это не работает благодаря требованию о необходимости OracleObjectMappingAttribute для каждого отображаемого атрибута (как в сгенерированных классах ODP.NET). Это кажется действительно глупым, поскольку я не буду использовать их вообще. Фактически, я могу заставить свой класс отображения работать, просто добавив три строки:

    [OracleObjectMappingAttribute("STATUS")] public string a;
    [OracleObjectMappingAttribute("CREATED_BY")] public string b;
    [OracleObjectMappingAttribute("CREATED_DATETIME")] public DateTime c;

Конечно, должен быть лучший способ, чем положить такой ужасный взлом? В конце концов, эти переменные никогда не используются вообще - ODP.NET, похоже, просто нужен для того, чтобы получить тип для сопоставления, - но я бы подумал, что это может быть достигнуто другим способом. Мысли?

Ответы [ 2 ]

2 голосов
/ 01 октября 2009

Что плохого в этих дополнительных атрибутах? Уже есть огромное количество атрибутов в классах и средах .net (например, WCF). Неприязнь к атрибутам почти такая же, как неприязнь к .NET.

В любом случае вы можете изучить возможности поставщика Oracle devart (http://www.devart.com/dotconnect/oracle/). У них тоже есть бесплатная версия. Работа с udts основана на строках, а не на атрибутах.

0 голосов
/ 21 мая 2014

Вы можете установить свой BusinessObject в качестве частного участника и сопоставить атрибуты с соответствующими свойствами.

Хотя это не обеспечивает никакой функциональности, по крайней мере, они будут работать правильно, если используются.

...