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?
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
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
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