title: How do I map from Oracle UDTs with ODP.NET without using OracleObjectMappingAttribute?
body: <p>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.</p>
  
  <p>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).</p>
  
  <p>We then use a separate mapping class, to map the custom class to one of our business objects (and back when saving).</p>
  
  <p>I am trying to find a better way of doing this.</p>
  
  <p>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.</p>
  
  <p>For example - a workflow UDT contains three items - a status, created time and created by.
  My UDT is nice and simple:</p>
  
  <pre><code>TYPE workflow_type AS OBJECT
  (status                                  VARCHAR2(8)
  ,created_by                              VARCHAR2(30)
  ,created_datetime            DATE
  );
  </code></pre>
  
  <p>As is the business object I want it to end up in:</p>
  
  <pre><code>public class Workflow
  {
      /// &lt;summary&gt;
      /// Gets the status of the workflow.
      /// &lt;/summary&gt;
      /// &lt;value&gt;The status.&lt;/value&gt;
      public string Status { get; private set; }
  
      /// &lt;summary&gt;
      /// Gets the Windows Logon Id of the user performing the action
      /// &lt;/summary&gt;
      public string CreatedBy{ get; private set; }
      /// &lt;summary&gt;
      /// Gets the time of the action 
      /// &lt;/summary&gt;
      public DateTime CreatedTime { get; private set; }
  }
  </code></pre>
  
  <p>I want to get from one to the other without having to add Oracle code to the business object.</p>
  
  <p>So my thought was to create a mapping class like this:</p>
  
  <pre><code>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;
      }
  }
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>    [OracleObjectMappingAttribute("STATUS")] public string a;
      [OracleObjectMappingAttribute("CREATED_BY")] public string b;
      [OracleObjectMappingAttribute("CREATED_DATETIME")] public DateTime c;
  </code></pre>
  
  <p>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?</p>