2009-10-01 8 views
9

La couche d'accès aux données dans notre application va utiliser la fonctionnalité UDT d'Oracle. Nous ne transmettrons que des objets UDT vers et depuis la base de données.Comment mapper des UDT Oracle avec ODP.NET sans utiliser OracleObjectMappingAttribute?

Pour le moment, nous générons les classes personnalisées en utilisant la fonction fournie avec ODP.NET (qui crée une classe vraiment horrible que nous ne voulons vraiment pas dans notre code). Nous utilisons ensuite une classe de mappage distincte pour mapper la classe personnalisée à l'un de nos objets métier (et à nouveau lors de la sauvegarde).

J'essaie de trouver une meilleure façon de le faire.

Je pensais que je supprimerais simplement les classes générées et que j'écrirais simplement une classe de mapping qui implémenterait IOracleCustomType. Les méthodes From/ToCustomObject mapperaient ensuite de mon UDT à mes objets métier. Cependant, cela m'a causé des problèmes lorsque je l'ai essayé - J'ai l'erreur "L'attribut d'objet n'est pas mappé à un membre de type personnalisé". Il semble que, de même que les deux méthodes, j'ai également besoin d'attributs dans ma classe de mappage - un attribut pour chaque élément de l'UDT. Par exemple, un workflow UDT contient trois éléments: un statut, un temps créé et créé par. Mon UDT est agréable et simple:

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

Comme l'objet métier que je veux finir dans:

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

Je veux obtenir de l'un à l'autre sans avoir à ajouter du code Oracle à l'objet métier.

Donc, ma pensée était de créer une classe de cartographie comme ceci:

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

Mais cela ne fonctionne pas grâce à l'exigence d'avoir besoin OracleObjectMappingAttribute pour chaque attribut à mapper (comme dans le ODP.NET généré Des classes). Cela semble vraiment stupide que je ne vais pas les utiliser du tout. En fait, je peux obtenir ma classe de cartographie pour travailler, tout en ajoutant trois lignes:

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

Il doit sûrement y avoir une meilleure façon que de mettre dans un tel horrible hack? Après tout, ces variables ne sont jamais utilisées du tout - ODP.NET semble juste en avoir besoin pour faire correspondre le type à - mais j'aurais pensé que cela pourrait être réalisé d'une manière différente. Pensées?

Répondre

2

En quoi ces attributs supplémentaires sont-ils si mauvais? Il existe déjà une quantité gigantesque d'attributs dans les classes et les frameworks .net (par exemple WCF). Le fait de ne pas aimer les attributs revient presque à ne pas aimer .NET.

Quoi qu'il en soit, vous pouvez explorer les possibilités du fournisseur Oracle de devart (http://www.devart.com/dotconnect/oracle/). Ils ont aussi une version gratuite. Son traitement avec udts est basé sur des chaînes pas sur les attributs.

+4

Ce qui est grave, c'est qu'ils ne devraient pas être nécessaires. Les propriétés elles-mêmes ne sont jamais obtenues ou définies, la seule raison pour laquelle elles sont nécessaires est que chaque propriété UDT semble avoir besoin de l'une de ces OracleObjectMappingAttribute. Il semble juste fou d'avoir un tas de propriétés publiques dans une classe qui ne sont jamais utilisées (et oui, elles doivent aussi être publiques!). Donc, je suppose que c'est le besoin pour les propriétés publiques que je questionne, plutôt que les attributs. – David

+0

Oh, et merci pour l'autre lien fournisseur oracle (malheureusement cela ne m'aidera pas personnellement car où je travaille c'est seulement ODP.NET qui est utilisé) – David

+0

Il y a en effet une certaine 'duplication' dans le code car il faut cartographier dans le code et de cartographier avec des attributs, mais je ne pense pas que ce soit un gros problème. C'est un problème mais un gros problème. – Theo

0

Vous pouvez définir votre BusinessObject en tant que membre privé et mapper les attributs aux propriétés respectives.

Bien que cela ne fournisse aucune fonctionnalité, au moins, ils fonctionneraient correctement s'ils étaient utilisés.

Questions connexes