【问题标题】:NullReferenceException mapping collection of enum with Fluent NHibernate automapping使用 Fluent NHibernate 自动映射枚举的 NullReferenceException 映射集合
【发布时间】:2011-02-10 05:40:30
【问题描述】:

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

public enum TransactionType
{
  ...
}

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

对 TransactionType 枚举的其他引用工作正常,但使用此集合时出现异常:“NHibernate.MappingException : Association references unmapped class: mynamespace.TransactionType”。

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

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

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

但这会导致以下异常...

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

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

任何帮助表示赞赏...

【问题讨论】:

    标签: nhibernate fluent-nhibernate


    【解决方案1】:

    也许这是 FluentNHibernate 中的最新修复,但这适用于 FluentNH v1.2.0.712。我相当有信心带有普通 *.hbm.xml 映射的 NHibernate 多年来一直支持这种类型的映射。

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

    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]
    

    ...这正是我所期望的。耶 NHibernate!

    【讨论】:

      【解决方案2】:

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

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

      希望这会有所帮助。

      【讨论】:

        【解决方案3】:

        我认为您不能映射枚举集合。大约一年前你肯定不能

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-19
          • 2013-04-04
          • 1970-01-01
          相关资源
          最近更新 更多