2012-01-12 3 views
2

En AccountType.cs je:Comment travailler avec Enums avec NHibernate?

namespace MooDB.Domain 
{ 
    public enum AccountType {Real, Demo, Fictional}; 
} 

En Account.cs je:

public class Account : Entity 
{   
    public virtual int Id { get; set; } 
    public virtual Broker Broker { get; set; } 
    public virtual string Name { get; set; } 
    public virtual string NickName { get; set; } 
    public virtual string AccountNumber { get; set; } 
    public virtual Currency Currency { get; set; } 
    public virtual AccountType AccountType { get; set; } 
    public virtual bool IsActive { get; set; } 
    public virtual bool IsDefault { get; set; } 
} 

Dans mon Account.hbm.xml je

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
        assembly="MooDB" 
        namespace="MooDB.Domain"> 

    <class name="MooDB.Domain.Account,MooDB" table="accounts"> 
    <id name="Id" column="accountId" type="Int32" unsaved-value="0"> 
     <generator class="native" /> 
    </id> 
    <version name="Version" column="version" type="integer" unsaved-value="0" /> 
    <many-to-one name ="Broker" column="brokerId" not-null="true" class="MooDB.Domain.Broker,MooDB" /> 
    <property name="Name" column="`name`" type="String" length="50" not-null="true" /> 
    <property name="NickName" column="nickName" type="String" length="50" not-null="true" /> 
    <property name="AccountNumber" column="accountNumber" type="String" length="50" not-null="true" /> 
    <many-to-one name ="Currency" column="currency" not-null="true" class="MooDB.Domain.Currency,MooDB" /> 
    <property name="AccountType" column="accountType" /> 
    <property name="IsActive" column="isActive" type="bool" not-null="true" /> 
    <property name="IsDefault" column="isDefault" type="bool" not-null="true" /> 
    </class> 
</hibernate-mapping> 

Mes regards de table de base de données comme:

CREATE TABLE [dbo].[accounts](
    [accountId] [int] IDENTITY(1,1) NOT NULL, 
    [brokerId] [int] NOT NULL, 
    [name] [nvarchar](50) NOT NULL, 
    [nickName] [nvarchar](50) NOT NULL, 
    [accountNumber] [nvarchar](50) NOT NULL, 
    [currency] [char](3) NOT NULL, 
    [accountType] [varchar](10) NOT NULL, 
    [isActive] [bit] NOT NULL, 
    [isDefault] [bit] NOT NULL, 
    [version] [int] NOT NULL, 
CONSTRAINT [PK_accounts] PRIMARY KEY CLUSTERED 
(
    [accountId] ASC 
) 

Lorsque je tente de tester une récupération d'un compte, je reçois cette erreur de NHibernate:

Test 'Test.RepoTest.CanGetAccountById' failed: NHibernate.Exceptions.GenericADOException : could not load an entity: [MooDB.Domain.Account#1][SQL: SELECT account0_.accountId as accountId3_0_, account0_.version as version3_0_, account0_.brokerId as brokerId3_0_, account0_.[name] as name4_3_0_, account0_.nickName as nickName3_0_, account0_.accountNumber as accountN6_3_0_, account0_.currency as currency3_0_, account0_.accountType as accountT8_3_0_, account0_.isActive as isActive3_0_, account0_.isDefault as isDefault3_0_ FROM accounts account0_ WHERE account0_.accountId=?] 
    ----> System.FormatException : Input string was not in a correct format. 

Tout ce que je veux faire est d'avoir une liste des types de compte dans mon application à des fins de validation. Je ne veux pas avoir de table de consultation dans ma base de données. Des idées de ce que je fais mal?

Répondre

6

Sur la cartographie AccountType ajouter l'attribut type avec la valeur suivante

NHibernate.Type.EnumStringType`1[[MooDB.Domain.AccountType, MooDB]], NHibernate 

En spécifiant un attribut type pour AccountType, nous disons NHibernate d'utiliser une classe personnalisée pour la conversion entre les types .NET et la base de données. NHibernate inclut EnumStringType<T> pour remplacer la conversion des valeurs d'énumération en valeurs de base de données afin que le nom de la chaîne soit stocké, et non la valeur numérique.

1

Je pense que NHibernate par défaut persisterait enum en tant qu'entier (puisque en .net enums sont en fait du sucre syntaxique sur ints), à moins que vous ne le disiez autrement. Si vous en avez vraiment besoin, vous devrez implémenter un IUserType. Un exemple similaire est la cartographie des chaînes en booléens et is covered here. Avec les énumérations, il suffirait de changer la logique dans NullSafeGet et NullSafeSet pour mapper à vos énumérations, éventuellement en utilisant les méthodes Enum.Parse ou TryParse.