NullReferenceException使用Fluent NHibernate自动化映射枚举的集合

时间:2010-04-20 16:28:35

标签: nhibernate fluent-nhibernate

我有一个包含枚举集合的类,如下所示。

public enum TransactionType
{
  ...
}

public class PaymentMethod
{
  ...
  public virtual IList<TransactionType> SupportedTransactionTypes { get; set; }
}

对TransactionType枚举的其他引用正常工作,但是对于这个集合,我得到一个异常:“NHibernate.MappingException:Association引用unmapped class:mynamespace.TransactionType”。

环顾四周似乎我需要指定元素映射的类型,即一对多,元素或复合元素。

我为PaymentMethod类设置了以下覆盖映射:

mapping.HasMany(x => x.TransactionTypes)
  .Element("TransactionTypeId"), x => x.Type<TransactionType>());

但这导致以下异常...

验证失败:System.NullReferenceException:未将对象引用设置为对象的实例。    在E:\ horn.horn \ orm \ fluentnhibernate \ Working \ src \ FluentNHibernate \ Conventions \ Inspections \ OneToManyInspector.cs:40行的FluentNHibernate.Conventions.Inspections.OneToManyInspector.get_Class()中    在FluentNHibernate.Conventions.ProxyConvention.Apply(ICollectionInstance实例)中的e:\ horn.horn \ orm \ fluentnhibernate \ Working \ src \ FluentNHibernate \ Conventions \ ProxyConvention.cs:第79行    在FluentNHibernate.Visitors.ConventionVisitor.Apply [TInspector,TInstance](IEnumerable convention,TInstance实例)中的e:\ horn.horn \ orm \ fluentnhibernate \ Working \ src \ FluentNHibernate \ Visitors \ ConventionVisitor.cs:第269行    在......

我在映射上尝试了很多不同的变体,包括TableName,KeyColumn和我能想到的任何其他东西,但是我无法使这个映射起作用。

任何帮助表示赞赏...

3 个答案:

答案 0 :(得分:3)

也许这是FluentNHibernate最近的修复,但这适用于FluentNH v1.2.0.712。我相信NHibernate与普通* .hbm.xml映射多年来一直支持这种映射。

这是对我有用的自动覆盖:

mapping.HasMany(x => x.SupportedTransactionTypes)
    .Element("TransactionTypeId");

...导致这个XML ......

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="so.Q2676867.PaymentMethod, so, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`PaymentMethod`">
    <id access="backfield" name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <column name="Id" />
      <generator class="identity" />
    </id>
    <bag name="SupportedTransactionTypes">
      <key>
        <column name="PaymentMethod_id" />
      </key>
      <element type="so.Q2676867.TransactionType, so, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <column name="TransactionTypeId" />
      </element>
    </bag>
  </class>
</hibernate-mapping>

......以及这些表:

create table [PaymentMethod] (
    Id INT IDENTITY NOT NULL,
   primary key (Id)
)

create table SupportedTransactionTypes (
    PaymentMethod_id INT not null,
   TransactionTypeId INT null
)

alter table SupportedTransactionTypes 
    add constraint FK738E3751B597A1C 
    foreign key (PaymentMethod_id) 
    references [PaymentMethod]

......这正是我所期待的。 Yay NHibernate!

答案 1 :(得分:1)

您可以将数据库中的集合作为管道分隔的字符串...

保留
    protected string _enumCollection = "";    
    public virtual ISet<MyEnum> EnumCollection
    {
        get
        {
            var set = new HashedSet<MyEnum>();

            if (string.IsNullOrEmpty(_enumString))
                return set;

            _enumCollection.Split(new[] {"|"}, StringSplitOptions.None).ToList()
                .ForEach(
                    x => set.Add((MyEnum)(Int32.Parse(x)))
                );
            return new HashedSet<MyEnum>(set);
        }
        set { _enumCollection = string.Join("|", value.Select(x => ((int)x).ToString()).ToArray()); }
    }

然后映射到字符串后备字段:

Map(x => x.EnumCollection).CustomType(typeof(string)).Access.CamelCaseField(Prefix.Underscore);

您需要使用辅助方法来添加/删除枚举,而不是使用集合本身的方法来更新支持字段。

public virtual void AddEnum(MyEnum enum)
        {
            if (!EnumCollection.Contains(enum))
            {
                var set = EnumCollection; //you need to get the collection
                set.Add(enum); //add enum to it
                EnumCollection= set; //then set the set again
            }
        }

        public virtual void RemoveEnum(MyEnum enum)
        {
            if (EnumCollection.Contains(enum))
            {
                var set = EnumCollection; //get collection
                set.Remove(enum); //add enum 
                EnumCollection= set; //re-set collection
            }
        }

希望这有帮助。

答案 2 :(得分:0)

我不认为你可以映射一组枚举。你肯定不会在一年左右之前