2009-10-01 12 views
9

La capa de acceso a datos en nuestra aplicación va a utilizar la funcionalidad UDT de Oracle. Solo pasaremos objetos UDT desde y hacia la base de datos.¿Cómo puedo mapear desde UDT de Oracle con ODP.NET sin utilizar OracleObjectMappingAttribute?

Por el momento, generamos las clases personalizadas utilizando la función provista con ODP.NET (que crea una clase realmente horrible que realmente no queremos en nuestra base de código).

A continuación, utilizamos una clase de asignación independiente, para asignar la clase personalizada a uno de nuestros objetos comerciales (y viceversa al guardar).

Estoy tratando de encontrar una mejor manera de hacerlo.

Pensé que simplemente me iría con las clases generadas y solo escribiría una clase de mapeo que implementara IOracleCustomType. Los métodos From/ToCustomObject se asignarían desde mi UDT a mis objetos comerciales. Sin embargo, esto me causó problemas cuando lo probé. Obtuve el error "El atributo de objeto no está asignado a un miembro de tipo personalizado". Parece que, además de los dos métodos, también necesito atributos en mi clase de mapeo, un atributo para cada elemento en el UDT.

Por ejemplo, un UDT de flujo de trabajo contiene tres elementos: un estado, tiempo creado y creado por. Mi UDT es agradable y simple:

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

Como es el objeto de negocio que yo quiero que terminan en:

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

quiero ir de uno a otro sin tener que agregar el código de Oracle al objeto de negocio.

Así que mi idea era crear una clase en el mapeo:

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

Pero esto no funciona gracias a la exigencia de tener OracleObjectMappingAttribute para cada atributo de ser asignada (como en el ODP.NET generada clases). Esto parece realmente estúpido ya que no los usaré en absoluto. De hecho, puedo conseguir mi clase de mapeo para trabajar, sólo mediante la adición de tres líneas:

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

Seguramente debe haber una mejor manera de poner en un truco tan horrible? Después de todo, estas variables nunca se usan en absoluto, ODP.NET parece necesitarlas para hacer que el tipo se asigne, pero pensé que esto podría lograrse de otra manera. ¿Pensamientos?

Respuesta

2

¿Qué hay de malo en esos atributos adicionales? Ya existe una cantidad descomunal de atributos en las clases y marcos .net (por ejemplo, WCF). Los atributos desagradables son casi lo mismo que desagradar a .NET.

De todos modos, puede explorar las posibilidades del proveedor de Oracle de devart (http://www.devart.com/dotconnect/oracle/). Ellos tienen una versión gratuita también. Su tratamiento con udts se basa en cadenas no en atributos.

+4

Lo malo es que no deberían ser necesarios. Las propiedades en sí nunca se obtienen o establecen, la única razón por la que se necesitan es porque cada propiedad UDT parece necesitar uno de esos OracleObjectMappingAttribute. Parece una locura tener un montón de propiedades públicas en una clase que nunca se usan (y sí, ¡también tienen que ser públicas!). Así que supongo que es la necesidad de las propiedades públicas que estoy cuestionando, en lugar de los atributos. – David

+0

Ah, y gracias por el otro enlace de proveedor de Oracle (por desgracia, esto no me ayudará personalmente, donde trabajo, solo se utiliza ODP.NET) – David

+0

Hay una cierta "duplicación" en el código porque hay que mapear en el código y para mapear con atributos, pero simplemente no creo que sea un gran problema. Es un problema pero no grande. – Theo

0

Puede establecer su BusinessObject como miembro privado y asignar los atributos a las propiedades respectivas.

Si bien esto no proporciona ninguna funcionalidad, al menos funcionaría correctamente si se utilizara.

Cuestiones relacionadas