如何在不使用 OracleObjectMappingAttribute 的情况下使用 ODP.NET 从 Oracle UDT 进行映射?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1505011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 19:07:36  来源:igfitidea点击:

How do I map from Oracle UDTs with ODP.NET without using OracleObjectMappingAttribute?

c#.netoracleodp.netuser-defined-types

提问by David

The data access layer in our application is going to be using the UDT functionality of Oracle. We will only be passing UDT objects to and from the database.

我们应用程序中的数据访问层将使用 Oracle 的 UDT 功能。我们只会将 UDT 对象传入和传出数据库。

At the moment, we generate the custom classes using the function provided with ODP.NET (which creates a truly horrible looking class that we really don't want in our codebase).

目前,我们使用 ODP.NET 提供的函数生成自定义类(这会创建一个看起来非常可怕的类,我们真的不希望在我们的代码库中使用它)。

We then use a separate mapping class, to map the custom class to one of our business objects (and back when saving).

然后我们使用一个单独的映射类,将自定义类映射到我们的业务对象之一(并在保存时返回)。

I am trying to find a better way of doing this.

我正试图找到一种更好的方法来做到这一点。

I thought I would just do-away with the generated classes and just write a mapping class that implemented IOracleCustomType. The From/ToCustomObject methods would then map from my UDT to my business objects. However, this caused me problems when I tried it - I got the error "Object attribute is not mapped to a custom type member". It appears that as well the two methods, I also need attributes in my mapping class - one attribute for each item in the UDT.

我想我会放弃生成的类,只编写一个实现 IOracleCustomType 的映射类。From/ToCustomObject 方法然后将从我的 UDT 映射到我的业务对象。但是,这在我尝试时给我带来了问题 - 我收到错误“对象属性未映射到自定义类型成员”。似乎除了这两种方法外,我还需要映射类中的属性——UDT 中的每个项目都有一个属性。

For example - a workflow UDT contains three items - a status, created time and created by. My UDT is nice and simple:

例如 - 工作流 UDT 包含三个项目 - 状态、创建时间和创建者。我的 UDT 很好很简单:

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

As is the business object I want it to end up in:

正如我希望它最终出现的业务对象一样:

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; }
}

I want to get from one to the other without having to add Oracle code to the business object.

我想在不必将 Oracle 代码添加到业务对象的情况下从一个到另一个。

So my thought was to create a mapping class like this:

所以我的想法是创建一个这样的映射类:

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;
    }
}

But this doesn't work thanks to the requirement of needing OracleObjectMappingAttribute for each attribute to be mapped (as in the ODP.NET generated classes). This appears really stupid as I won't be using them at all. In fact, I can get my mapping class to work, just by adding in three lines:

但由于需要为每个要映射的属性(如在 ODP.NET 生成的类中)使用 OracleObjectMappingAttribute 的要求,这不起作用。这看起来真的很愚蠢,因为我根本不会使用它们。事实上,我可以让我的映射类工作,只需添加三行:

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

Surely there must be a better way than putting in such a horrible hack? Afterall, these variables never get used at all - ODP.NET just appears to need them for getting the type to map to - but I would have thought this could be achieved in a different way. Thoughts?

肯定有比进行如此可怕的黑客攻击更好的方法吗?毕竟,这些变量根本不会被使用——ODP.NET 似乎只是需要它们来获取要映射到的类型——但我认为这可以通过不同的方式实现。想法?

回答by tuinstoel

What is so bad about those extra attributes? There is already a ginormous amount of attributes in the .net classes and frameworks (for instance WCF). Disliking attributes is almost the same as disliking .NET .

这些额外的属性有什么不好?.net 类和框架(例如 WCF)中已经有大量的属性。不喜欢属性几乎与不喜欢 .NET 相同。

Anyway you can explore the possibilities of devart's Oracle provider (http://www.devart.com/dotconnect/oracle/). They have a free version too. Its dealing with udts is based on strings not on attributes.

无论如何,您可以探索 devart 的 Oracle 提供程序 ( http://www.devart.com/dotconnect/oracle/)的可能性。他们也有免费版本。它处理 udts 是基于字符串而不是属性。

回答by Michael Hsu

You could set your BusinessObject as a private member and map the attributes to the respective properties.

您可以将您的 BusinessObject 设置为私有成员并将属性映射到相应的属性。

While this doesn't provide any functionality, at least they would function correctly if used.

虽然这不提供任何功能,但至少如果使用它们会正常运行。