Fluent NHibernate:我如何使用 Int64 作为 ID?

发布于 2024-08-19 23:09:36 字数 3031 浏览 0 评论 0原文

我对 ORM、NHibernate 和 FluentNH 的整个概念还很陌生,我正在尝试完成一些看起来很简单的事情...

我正在尝试检索一个在其类中具有定义为 Int64 的字段的对象。该字段是映射文件中定义的 ID。

当尝试从数据库检索记录时,NHibernate 返回以下错误消息:“提供了错误类型的 id。预期:System.Int32,得到 System.Int64”

我有一个非常简单的对象:

public class Holiday
{
    public virtual Int64 HolidayID { get; set; }
    public virtual string Name { get; set; }
    public virtual int Day { get; set; }
    public virtual int Month { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual HolidayGroup Group { get; set; }

    public Holiday() { }

}

映射文件(对于 FluentNH)如下:

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID);
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}

表结构(由 NH 生成)如下:

CREATE TABLE [dbo].[Holiday](
 [HolidayID] [bigint] IDENTITY(1,1) NOT NULL,
 [Name] [nvarchar](255) NULL,
 [Day] [int] NULL,
 [Month] [int] NULL,
 [IsActive] [bit] NULL,
 [HolidayGroup_id] [int] NULL,
PRIMARY KEY CLUSTERED 
(
 [HolidayID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

最后,我尝试使用以下方法检索 Holiday 实例:

    public static Holiday Get(Int64 _holidayID)
    {
        Holiday _holiday = new Holiday();

        try
        {
            using (var session = Global.NHibernate_SessionFactory.OpenSession())
            {
                _holiday = session.Get<Holiday>(_holidayID); // EXCEPTION OCCURS HERE
            }
        }
        catch (Exception _ex)
        {
            // TODO : Implement proper logging
        }

        return _holiday;
    }

我做错了什么?缺少什么?当删除表并使用 Int32 作为 ID 重新定义对象时,一切正常!我需要使用更大的类型!

非常感谢!

编辑1:正如Aaronaught提到的那样,我同意,我对 Int64 的需要对于存储假期来说是有点开销......但是一会儿,让我们忘记“假期” “ 概念。我要如何处理我的日志表(每秒 5 到 10 个事件(行)!)。谢谢!

编辑2: @Paco:我正在使用NHibernate 2.1.2.4000和FluentNH 1.0.0.614

编辑3:重新阅读Daniel Schilling的解决方案后,重建了一个(全新的)简单的 Holiday 对象,它使用 Int64 作为 ID。我能够成功地从数据库检索记录。一旦我向 Group 对象添加了关系,在实例化 Holiday 对象时,我收到了与之前相同的错误消息...这是 HolidayGroup 类和映射,以防万一您可以告诉我什么我做错了...

public class HolidayGroup
{
    public virtual int HolidayGroupID { get; set;}
    public virtual string Name { get; set; }
    public virtual string Notes { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual IList<Holiday> Holidays { get; set; }

    public HolidayGroup()
    {
        Holidays = new List<Holiday>();
    }
}

public HolidayGroupMap() { Id(x => x.HolidayGroupID); 地图(x => x.Name); Map(x => x.Notes); Map(x => x.IsActive); HasMany(x => x.Holidays) .Cascade.All() }

I'm quite new to the whole concept of ORM, NHibernate and FluentNH, and i'm trying to accomplish something that seems so simple...

I'm trying to retrieve an object that has a field defined as Int64 in it's class. This field would be the ID, as defined in the Map file.

When trying to retrieve a record from the DB, NHibernate returns the following error message : "Provided id of the wrong type. Expected: System.Int32, got System.Int64"

I have a very simple object :

public class Holiday
{
    public virtual Int64 HolidayID { get; set; }
    public virtual string Name { get; set; }
    public virtual int Day { get; set; }
    public virtual int Month { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual HolidayGroup Group { get; set; }

    public Holiday() { }

}

the Mapping file (for FluentNH) is the following :

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID);
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}

the table structure (generated by NH) is the following:

CREATE TABLE [dbo].[Holiday](
 [HolidayID] [bigint] IDENTITY(1,1) NOT NULL,
 [Name] [nvarchar](255) NULL,
 [Day] [int] NULL,
 [Month] [int] NULL,
 [IsActive] [bit] NULL,
 [HolidayGroup_id] [int] NULL,
PRIMARY KEY CLUSTERED 
(
 [HolidayID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

and finally, i am trying to retrieve the Holiday instance using this:

    public static Holiday Get(Int64 _holidayID)
    {
        Holiday _holiday = new Holiday();

        try
        {
            using (var session = Global.NHibernate_SessionFactory.OpenSession())
            {
                _holiday = session.Get<Holiday>(_holidayID); // EXCEPTION OCCURS HERE
            }
        }
        catch (Exception _ex)
        {
            // TODO : Implement proper logging
        }

        return _holiday;
    }

What am i doing wrong?? What's missing? When deleting the table and redefining my object using an Int32 for the ID, everything works! I need use a bigger type!

Many thanks!

EDIT 1 : As Aaronaught mentions, i agree, my need for an Int64 is a bit of overhead for storing holidays... But for a second, let's forget the "Holidays" concept. What am i going to do with my logging table (5 to 10 events (rows) per seconds!). Thanks!

EDIT 2 : @Paco : I'm using NHibernate 2.1.2.4000 and FluentNH 1.0.0.614

EDIT 3 : After rerading Daniel Schilling's solution, rebuilt a (brand new) simple Holiday object that used an Int64 as an ID. I was able to retrieve a record from the DB successfully. As soon as i added a relationship to a Group object, when instanciating a Holiday object i received the same error message as earlier... Here is the HolidayGroup class and mapping, in case you can tell me what i did wrong...

public class HolidayGroup
{
    public virtual int HolidayGroupID { get; set;}
    public virtual string Name { get; set; }
    public virtual string Notes { get; set; }
    public virtual bool IsActive { get; set; }
    public virtual IList<Holiday> Holidays { get; set; }

    public HolidayGroup()
    {
        Holidays = new List<Holiday>();
    }
}

public HolidayGroupMap()
{
Id(x => x.HolidayGroupID);
Map(x => x.Name);
Map(x => x.Notes);
Map(x => x.IsActive);
HasMany(x => x.Holidays)
.Cascade.All()
}

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

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

发布评论

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

评论(2

冷默言语 2024-08-26 23:09:36

我知道仅仅说它对我有用并没有多大帮助,但是......它对我有用。我在 Fluent NHibernate 中一直使用 long 作为我的 id。我的版本:

  • NHibernate 2.1.0.4000
  • Fluent NHibernate 1.0.0.598

正如其他人评论的那样,这可能是 NHibernate 或 Fluent NHibernate 的问题。要找出问题所在,请使用 ExportTo 方法找出 Fluent NHibernate 生成的 *.hbm.xml 内容。请参阅 https://github.com/jagregory/ 上的“导出映射”部分fluent-nhibernate/wiki/Fluent-configuration

如果 FluentNHibernate 工作正常,您应该

<id name="HolidayID" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="HolidayID" />
  <generator class="identity" />
</id>

在 *.Holiday.hbm.xml 文件中看到类似 ... ... 的内容。如果您看到 System.Int64,那么问题一定出在 NHibernate 或您的代码中。如果问题出在 NHibernate - 它一定是自 2.1.0 以来引入的问题(因为它对我有用)。尝试使用我正在使用的相同版本。如果问题消失了,那么就是新版本 NHibernate 的问题。

如果这不能解决问题,那么(不幸的是)问题很可能出在您自己的代码中。 Global.NHibernate_SessionFactory是如何实例化的?是否有可能使用一个 Configuration 对象来导出架构,而另一个实例正在创建 SessionFactory

这些就是我的所有想法。祝你好运。

编辑1:
关于与 HolidayGroup 的关系(抱歉 - 之前没有注意到):我认为你的意思是 References 而不是 HasOne - 请参阅 问题 1622007。另外,您需要标记关系的一侧 Inverse() - 通常您会将其放在 HasMany 一侧。

编辑2:
错误应用的 HasOne 肯定是此错误的根源。默认情况下,一对一关系映射为两个共享主键的表。子级的主键列通常与父级的主键具有外键关系。通过说“Holiday has-one HolidayGroup”,您将 Holiday 设置为父级,将 HolidayGroup 设置为子级(这与您想要的相反)。

当NHibernate尝试加载与HolidayGroup关联的Holiday时,它将获取HolidayGroup的Int32 ID并尝试检索具有相同ID的Holiday。然而,Holiday 有一个 Int64 ID,因此会出现错误。

在“EDIT 1”下进行更改,这个问题就会消失。

  1. HasOne 更改为 References
  2. Inverse() 添加到 HolidayGroupHasMany

I know it's not really helpful to just say that it works for me, but ... it works for me. I use long for my id's all the time with Fluent NHibernate. My versions:

  • NHibernate 2.1.0.4000
  • Fluent NHibernate 1.0.0.598

As others have commented, it's possible that this could be a problem with NHibernate or Fluent NHibernate. To figure out where the problem is, use the ExportTo method to find out what *.hbm.xml Fluent NHibernate is generating. See the "Exporting mappings" section on https://github.com/jagregory/fluent-nhibernate/wiki/Fluent-configuration.

If FluentNHibernate is working correctly, you should see something like ...

<id name="HolidayID" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
  <column name="HolidayID" />
  <generator class="identity" />
</id>

... in the *.Holiday.hbm.xml file. If you see that System.Int64, then the issue must be in NHibernate or in your code. If the problem is with NHibernate - it must be a problem introduced since 2.1.0 (since it works for me). Try using the same version I'm using. If the problem goes away, then it was the new version of NHibernate's fault.

If that doesn't fix the problem, then (unfortunately) the problem most likely lies in your own code. How is Global.NHibernate_SessionFactory instantiated? Is it possible that one Configuration object is being used to export the schema and another instance is creating the SessionFactory?

Those are all the ideas I have. Good luck.

EDIT 1:
Regarding the relationship to HolidayGroup (sorry - didn't notice that before): I think you mean References instead of HasOne - see question 1622007. Also, you need to mark one side of the relationship Inverse() - typically you would put that on the HasMany side.

EDIT 2:
The incorrectly applied HasOne is surely the source of this error. One-to-one relationships are mapped by default with two tables that share primary keys in common. The child's primary key column would typically have a foreign key relationship to the parent's primary key. By saying "Holiday has-one HolidayGroup", you set Holiday up as the parent and HolidayGroup as the child (which is the reverse of what you wanted).

When NHibernate tries to load the Holiday that is associated with the HolidayGroup, it will take HolidayGroup's Int32 ID and try to retrieve a Holiday that has the same ID. However, Holiday has a Int64 ID, hence the error.

Make the changes under "EDIT 1", and this problem should go away.

  1. Change the HasOne to References.
  2. Add Inverse() to HolidayGroup's HasMany.
爱情眠于流年 2024-08-26 23:09:36

你试过这个吗?

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID).SetAttribute("type", "Int64");
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}

Have you tried this?

public class HolidayMap : ClassMap<Holiday>
{
    public HolidayMap()
    {

        Id(x => x.HolidayID).SetAttribute("type", "Int64");
        Map(x => x.Name);
        Map(x => x.Day);
        Map(x => x.Month);
        Map(x => x.IsActive);
        HasOne(x => x.Group);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文