2010-05-20 4 views
6

J'ai une requête nHibernate en utilisant Criteria, et j'essaie de convertir une chaîne en booléen dans la requête elle-même. Je l'ai fait la même chose avec la coulée d'une chaîne à int, et qui fonctionne bien (la propriété « DataField » est « 1 » comme une chaîne):Chaîne de conversion en booléen à l'aide des critères nHibernate

var result = Session 
    .CreateCriteria<Car>() 
    .Add(Restrictions.Eq((Projections.Cast(NHibernateUtil.Int32, 
    Projections.Property("DataField"), 1)) 
    .List<Car>(); 

tx.Commit(); 

Mais je suis en train de faire la même chose avec bool, mais Je ne reçois pas le résultat escompté:

var result = Session 
    .CreateCriteria<Car>() 
    .Add(Restrictions.Eq((Projections.Cast(NHibernateUtil.bool, 
    Projections.Property("DataField"), true)) 
    .List<Car>(); 

tx.Commit(); 

« DataField » est la chaîne « True », mais le résultat dans une liste vide, où il doit contenir 100 éléments avec la chaîne de propriété « DataField » « True ". J'ai essayé avec la chaîne "vrai", et "1", mais le résultat est toujours une liste vide.

[EDIT]

Comme commenté ci-dessous, je pouvais vérifier la chaîne « Vrai » ou « Faux », mais je dirais que cela est une question plus générale que juste pour le booléenne. Notez que l'idée est d'avoir une sorte de représentation de valeur de clé des données, où la valeur peut être différents types de données. J'ai besoin de la table de valeurs pour contenir toutes les données, donc stocker les données sous forme de chaîne semble être la solution la plus propre!

J'ai été capable d'utiliser la méthode ci-dessus pour stocker int et double comme chaîne, et pour la distribution dans la requête, mais je n'ai pas réussi à utiliser la même méthode pour DateDime et Boolean.

Et pour DateTime il est crucial d'avoir l'objet DateTime réel.

Comment est-ce que je peux faire le moulage de chaîne en booléen, et la chaîne au travail de DateTime dans les requêtes?

Merci

+1

Je ne comprends pas pourquoi ne pas simplement 'Restrictions.Eq (" DataField "," True ")' –

+0

Vous avez raison. Pour le booléen je pourrais facilement aller pour la comparaison de chaîne, mais pour DateTime j'ai le même problème que bool, et là il est crucial de transformer la chaîne en un objet DateTime –

+0

pourquoi avez-vous un champ datetime mappé comme chaîne? –

Répondre

5

Malheureusement, ce que vous essayez d'atteindre va être difficile à faire, car il va à l'encontre du grain de ce que le NHibernate et le SGBDR essaie de faire pour vous. En utilisant des données non typées, vous éviterez beaucoup des gains que vous procure un RDBM.

Sans un schéma complet, je ne peux que deviner. Comment savez-vous quel est le bon type pour le champ? Je suppose que vous avez une colonne 'type' qui indique si la valeur est un entier, un booléen, une date, etc. Si c'est le cas, continuez avec une colonne d'identifiant de type, plus une colonne séparée pour chaque type de données. Ce n'est pas plus complexe que ce que vous faites, car il y a déjà des requêtes séparées pour chaque type de données, et vous obtenez la clarté, la vérification des types et la possibilité d'indexation. Si vous voulez vous prémunir contre la possibilité de définir plusieurs valeurs (par exemple, des valeurs dans plusieurs colonnes de type), vous pouvez créer une contrainte sur la table qui vérifie que chaque ligne définit uniquement une valeur pour au plus un type de données . (Vous pouvez également vérifier que la colonne pour le type spécifié n'est pas NULL, si cela est approprié pour votre cas.)

Altenrativement, vous pouvez faire en sorte que nHibernate gère les différents types et qu'il le fasse tout seul. NHibernate peut carte hiearchies de classe aux tables, vous pouvez donc créer des entités comme celui-ci:

public class AbstractProperty 
{ 
    // concrete name - persisted 
    public String Name { get; set; etc.. } 

    // owner property as well? 

    // abstract value provided by subclasses. This property is not persisted. 
    // used simply to provide polymorphic access to the value. 
    public abstract Object Value { get; set; } 
} 

public class DateProperty : AbstractProperty 
{ 
    // concrete date property 
    public Date date { get; set; etc.. } 

    // value delegates to date property 
    public Object value { get; set; } 
} 

Avec ce système en place, vous avez la possibilité de récupérer les valeurs avec un type de données spécifique, où, par exemple, les utilisations de la requête l'entité DateProperty Explicity renvoie DateProperty instances.Vous pouvez également écrire des requêtes pouvant renvoyer plusieurs types, dont le type statique est AbstractProperty. Vous pouvez ensuite utiliser les contrôles visitor pattern ou 'is' sur la propriété AbstractProperty pour déterminer le type et transtyper en un type concret pour extraire la valeur.

Un gourou nHibernate peut être en mesure de vous aider à corriger la distribution, mais à long terme, je recommande d'utiliser des types de données réels dans votre base de données. Cela vous sauvera des maux de tête plus tard.

+0

Merci pour la bonne réponse. Je vais regarder dans votre solution! –

+1

C'est ce que j'aurais suggéré, aussi; L'utilisation de l'héritage dans Hibernate vous permet de lancer une requête pour n'importe quelle propriété générique, mais vous pouvez alors avoir une table pour chaque type avec la colonne correctement typée dans le schéma. – RMorrisey

Questions connexes