首页 文章

使用流利的nhibernate映射枚举

提问于
浏览
31

我正在按照http://wiki.fluentnhibernate.org/Getting_started教程使用Fluent NHibernate创建我的第一个NHibernate项目

我有2张 table

1)帐户与字段

Id
AccountHolderName
AccountTypeId

2)带有字段的AccountType

Id
AccountTypeName

现在,帐户类型可以是Savings或Current所以表AccountTypes存储2行1 - Savings 2 - Current

对于AccoutType表,我已经定义了枚举

public enum AccountType {
    Savings=1,
    Current=2
}

对于Account表,我定义了实体类

public class Account {
    public virtual int Id {get; private set;}
    public virtual string AccountHolderName {get; set;}
    public virtual string AccountType {get; set;}
}

流畅的nhibernate映射是:

public AgencyMap() {
    Id(o => o.Id);
    Map(o => o.AccountHolderName);
    Map(o => o.AccountType);
}

当我尝试运行解决方案时,它给出了一个异常 - InnerException = {“(XmlDocument)(2,4):XML验证错误:命名空间'urn:nhibernate-mapping-2.2'中的元素'class'具有不完整的内容 . 期望的可能元素列表:'命名空间'中的元,子选择,缓存,同步,注释,tuplizer,id,composite-id'...

我想那是因为我还没有为AccountType指定任何映射 .

问题是:

  • 如何使用AccountType枚举而不是AccountType类?

  • 也许我走错了路 . 有一个更好的方法吗?

谢谢!

3 回答

  • 59

    以下显然不再有效https://stackoverflow.com/a/503327/189412

    这样做怎么样:

    public AgencyMap() {
        Id(o => o.Id);
        Map(o => o.AccountHolderName);
        Map(o => o.AccountType).CustomType<AccountType>();
    }
    

    自定义类型处理一切:)

  • 1
    public class Account {
        public virtual int Id {get; private set;}
        public virtual string AccountHolderName {get; set;}
        public virtual AccountType AccountType {get; set;}
    }
    
    public AgencyMap() {
        Id(o => o.Id);
        Map(o => o.AccountHolderName);
        Map(o => o.AccountType);
    }
    

    如果要覆盖需要为其提供约定,Fluent NHibernate默认将枚举值保存为字符串 . 就像是:

    public class EnumConvention :
        IPropertyConvention, 
        IPropertyConventionAcceptance
    {
        #region IPropertyConvention Members
    
        public void Apply(IPropertyInstance instance)
        {
            instance.CustomType(instance.Property.PropertyType);
        }
    
        #endregion
    
        #region IPropertyConventionAcceptance Members
    
        public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
        {
            criteria.Expect(x => x.Property.PropertyType.IsEnum ||
            (x.Property.PropertyType.IsGenericType && 
             x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
             x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
            );
        }
    
        #endregion
    }
    

    几乎忘了您还需要将常规添加到您的流畅配置中 . 您可以在添加映射的同一位置执行此操作:

    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<BillingRecordMap>()
    .Conventions.AddFromAssemblyOf<EnumConvention>()
    
  • 36

    一个很好的方法是实现IUserType接口和创建一个带有写入和读取规则的CustomType,这是布尔的一个例子:

    public class CharToBoolean : IUserType
    {
        public SqlType[] SqlTypes => new[] { NHibernateUtil.String.SqlType };
    
        public Type ReturnedType => typeof(bool);
    
        public bool IsMutable =>true;
    
        public object Assemble(object cached, object owner)
        {
            return (cached);
        }
    
        public object DeepCopy(object value)
        {
            return (value);
        }
    
        public object Disassemble(object value)
        {
            return (value);
        }
    
        public new bool Equals(object x, object y)
        {
            if (ReferenceEquals(x, y)) return true;
    
            var firstObject = x as string;
            var secondObject = y as string;
    
            if (string.IsNullOrEmpty(firstObject) || string.IsNullOrEmpty(secondObject)) return false;
    
            if (firstObject == secondObject) return true;
            return false;
        }
    
        public int GetHashCode(object x)
        {
            return ((x != null) ? x.GetHashCode() : 0);
        }
    
        public object NullSafeGet(IDataReader rs, string[] names, object owner)
        {
            var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);
    
            if (obj == null) return null;
    
            var value = (string)obj;
    
            return value.ToBoolean();
        }
    
        public void NullSafeSet(IDbCommand cmd, object value, int index)
        {
            if(value != null)
            {
                if ((bool)value)
                {
                    ((IDataParameter)cmd.Parameters[index]).Value = "S";
                }
                else
                {
                    ((IDataParameter)cmd.Parameters[index]).Value = "N";
                }
            }
            else
            {
                ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
            }
        }
        public object Replace(object original, object target, object owner)
        {
            return original;
        }
    }
    

    }

    映射:

    this.Map(x => x.DominioGenerico).Column("fldominiogen").CustomType<CharToBoolean>();
    

    这是一个示例,但您可以使用其他类型执行此操作 .

相关问题