2009-10-01 7 views
9

Il livello di accesso ai dati nella nostra applicazione utilizzerà la funzionalità UDT di Oracle. Passeremo solo oggetti UDT da e verso il database.Come mappare da Oracle UDT con ODP.NET senza utilizzare OracleObjectMappingAttribute?

Al momento, generiamo le classi personalizzate utilizzando la funzione fornita con ODP.NET (che crea una classe dall'aspetto davvero orribile che davvero non vogliamo nella nostra base di codice).

Quindi viene utilizzata una classe di mappatura separata, per associare la classe personalizzata a uno dei nostri oggetti di business (e viceversa durante il salvataggio).

Sto cercando di trovare un modo migliore per farlo.

Ho pensato di eliminare le classi generate e di scrivere solo una classe di mappatura che implementasse IOracleCustomType. I metodi From/ToCustomObject sarebbero quindi mappati dal mio UDT ai miei oggetti di business. Tuttavia, questo mi ha causato problemi quando l'ho provato - Ho ricevuto l'errore "L'attributo dell'oggetto non è mappato su un membro del tipo personalizzato". Sembra che anche i due metodi, ho bisogno anche di attributi nella mia classe di mappatura - un attributo per ogni elemento nell'UDT.

Ad esempio: un flusso di lavoro UDT contiene tre elementi: uno stato, l'ora creata e creata da. mio UDT è bello e semplice:

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

Come è l'oggetto di business voglio che finire 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; } 
} 

voglio ottenere da uno all'altro senza dover aggiungere il codice Oracle all'oggetto aziendale.

Quindi il mio pensiero è stato quello di creare una classe di mappatura come questo:

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

Ma questo non funziona, grazie al requisito di aver bisogno di OracleObjectMappingAttribute per ogni attributo da mappare (come nel ODP.NET generato classi). Questo sembra davvero stupido perché non li userò affatto. In effetti, posso avere la mia classe di mappatura a lavorare, solo con l'aggiunta di tre linee:

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

Sicuramente ci deve essere un modo migliore di mettere in un hack così orribile? Dopotutto, queste variabili non vengono mai usate affatto - ODP.NET sembra averne bisogno per far sì che il tipo venga mappato - ma avrei pensato che questo potesse essere ottenuto in un modo diverso. Pensieri?

risposta

2

Cosa c'è di così male in questi attributi extra? Esiste già una quantità enorme di attributi nelle classi .net e framework (ad esempio WCF). Non apprezzare gli attributi è quasi la stessa cosa che non piace a .NET.

In ogni caso è possibile esplorare le possibilità del provider Oracle di devart (http://www.devart.com/dotconnect/oracle/). Hanno anche una versione gratuita. La sua gestione di udts è basata su stringhe non sugli attributi.

+4

Ciò che è male è che non dovrebbero essere necessari. Le proprietà stesse non vengono mai acquisite o impostate, l'unica ragione per cui sono necessarie è perché ogni proprietà UDT sembra aver bisogno di uno di questi OracleObjectMappingAttribute. Sembra pazzesco avere un sacco di proprietà pubbliche in una classe che non vengono mai utilizzate (e sì, devono anche essere pubbliche!). Quindi immagino sia la necessità delle proprietà pubbliche che sto interrogando, piuttosto che degli attributi. – David

+0

Oh, e grazie per l'altro link del provider oracle (purtroppo questo non mi aiuterà personalmente come dove lavoro è solo ODP.NET che viene utilizzato) – David

+0

C'è davvero un po 'di "duplicazione" nel codice perché devi mappare nel codice e per mappare con attributi ma non penso che sia un grosso problema. È un problema ma nog uno grande. – Theo

0

È possibile impostare BusinessObject come membro privato e mappare gli attributi alle rispettive proprietà.

Anche se questo non fornisce alcuna funzionalità, almeno funzionerebbero correttamente se utilizzati.

Problemi correlati