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

发布于 2024-08-29 17:52:50 字数 1327 浏览 3 评论 0原文

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

public enum TransactionType
{
  ...
}

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

对 TransactionType 枚举的其他引用工作正常,但使用此集合时出现异常:“NHibernate.MappingException:关联引用未映射的类: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 中的 FluentNHibernate.Conventions.Inspections.OneToManyInspector.get_Class() 处:第 40 行 在 e:\horn.horn\orm\fluentnhibernate\Working\src\FluentNHibernate\Conventions\ProxyConvention.cs 中的 FluentNHibernate.Conventions.ProxyConvention.Apply(ICollectionInstance 实例):第 79 行 在FluentNHibernate.Visitors.ConventionVisitor.Apply [TInspector,TInstance](IEnumerable约定,TInstance实例)在e:\horn.horn\orm\fluentnhibernate\Working\src\FluentNHibernate\Visitors\ConventionVisitor.cs:第269行 at ...

我已经尝试了很多不同的映射变体,包括 TableName、KeyColumn 和我能想到的任何其他内容,但我无法使此映射发挥作用。

任何帮助表示赞赏...

I have a class that contains a collection of enumeration as follows.

public enum TransactionType
{
  ...
}

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

Other references to the TransactionType enumeration are working correctly but with this collection I get an exception: "NHibernate.MappingException : Association references unmapped class: mynamespace.TransactionType".

Looking around it seems like I needed to specify the type of element mapping, i.e. one-to-many, element, or composite-element.

I have setup the following override mappings for the PaymentMethod class:

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

But this causes the following exception...

Validation failed: System.NullReferenceException: Object reference not set to an instance of an object.
at FluentNHibernate.Conventions.Inspections.OneToManyInspector.get_Class() in e:\horn.horn\orm\fluentnhibernate\Working\src\FluentNHibernate\Conventions\Inspections\OneToManyInspector.cs:line 40
at FluentNHibernate.Conventions.ProxyConvention.Apply(ICollectionInstance instance) in e:\horn.horn\orm\fluentnhibernate\Working\src\FluentNHibernate\Conventions\ProxyConvention.cs:line 79
at FluentNHibernate.Visitors.ConventionVisitor.Apply[TInspector,TInstance](IEnumerable conventions, TInstance instance) in e:\horn.horn\orm\fluentnhibernate\Working\src\FluentNHibernate\Visitors\ConventionVisitor.cs:line 269
at ...

I have tried a lot of different variations on the mapping, including TableName, KeyColumn and anything else I can think of but I can't get this mapping to work.

Any help appreciated...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

西瑶 2024-09-05 17:52:50

也许这是 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!

Perhaps this is a recent fix in FluentNHibernate, but this works with FluentNH v1.2.0.712. I'm fairly confident that NHibernate with plain *.hbm.xml mappings has supported this type of mapping for years.

This is the automapping override that worked for me:

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

...which results in this 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>

... and these tables:

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]

... which is exactly what I would expect. Yay NHibernate!

二货你真萌 2024-09-05 17:52:50

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

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

希望这有帮助。

You could persist the collection in the database as a pipe-delimited string...

    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()); }
    }

and then map to the string backing field:

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

You'll need to use helper methods to add/remove enums rather than using the methods on the collection itself in order to update the backing field.

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

Hope this helps.

爱情眠于流年 2024-09-05 17:52:50

我不认为你可以映射枚举的集合。大约一年前你当然不能

I dont think you can map a collection of enums. You certainly couldnt a year or so ago

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文