使用nhibernate更新对象抛出InvalidCastException(但保存不会)

时间:2011-11-09 03:36:48

标签: nhibernate npgsql

我面临着一个非常奇怪的问题(我必须做错事,只是找不到我的错误!)。当某些POCO保存到数据库中时,没有任何反应。当相同的POCO更改了某些属性时,在会话刷新期间出现InvalidCastException,并且永远不会更新行。这是详细信息:

我声明了以下类:

namespace Data
{
    public class Picture
    {
        public virtual int picid { get; set; }
        public virtual int width { get; set; }
        public virtual int height { get; set; }
        public virtual string path { get; set; }
        public virtual string thumbnail { get; set; }
        public virtual int userid { get; set; }
        public virtual int? placeid { get; set; }
        public virtual int? eventid { get; set; }
        public virtual DateTime? approved { get; set; }
        public virtual DateTime date { get; set; }
        public virtual bool finished { get; set; }

        public virtual User User { get; set; }
        public virtual Place Place { get; set; }
        public virtual Event Event { get; set; }

        public virtual ISet<PictureVote> Votes { get; set; }
    }

}

以及它的以下映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Data" namespace="Data">
  <class name="Picture" table="pictures">
    <id name="picid">
        <generator class="sequence">
            <param name="sequence">pictures_picid_seq</param>
        </generator>
    </id>
    <property name="path" />
    <property name="width" />
    <property name="height" />
    <property name="thumbnail" />
    <property name="userid" />
    <property name="placeid" not-null="false" />
    <property name="eventid" not-null="false" />
    <property name="approved" />
    <property name="date" />
    <property name="finished" />

    <many-to-one name="User" column="userid" class="Data.User,Data" insert="false" />
    <many-to-one name="Place" column="placeid" class="Data.Place,Data" insert="false" />
    <many-to-one name="Event" column="eventid" class="Data.Event,Data" insert="false" />
    <set name="Votes">
        <key column="picid" />
        <one-to-many class="PictureVote" />
    </set>
  </class>

</hibernate-mapping>

我检查了表定义,所有类型似乎都是根据定义的类(postgresql):

                                      Table "public.pictures"
  Column   |            Type             |                        Modifiers                        
-----------+-----------------------------+----------------------------------------------------------
 picid     | integer                     | not null default nextval('pictures_picid_seq'::regclass)
 path      | character varying(250)      | not null
 thumbnail | character varying(250)      | not null
 userid    | integer                     | not null
 placeid   | integer                     |
 date      | timestamp without time zone | not null
 finished  | boolean                     | not null default false
 width     | integer                     | not null
 height    | integer                     | not null
 eventid   | integer                     |
 approved  | timestamp without time zone |

在代码中,以下工作正常并在图片表中插入一行: ... ...

var plpic = new Picture
                {
                   date = DateTime.Now,
                   width = img.Width,
                   height = img.Height,
                   path = pic_server_path,
                   thumbnail = thumb_server_path,
                   userid = CustomUserManagement.User.userid,
                   finished = false,
                   approved = null,
                   placeid = placeid
                };
                session.Save(plpic);
                session.Flush ();

... ... 每次都可以正常工作(是的,我很快就会把它包装成交易)。

但是,稍后,以下NEVER工作(这是MVC操作中的代码): ... ...

    Picture pic = session.Get<Picture>(picid);
            // While debugging, I verified that the "pic" object above is retrieved just fine.
            if (pic.userid != CustomUserManagement.User.userid || ModelState.IsValid == false)
                return Json (new { status = "error" });

            using (ITransaction tx = session.BeginTransaction()) {
                try
            {
                pic.finished = true;

                tx.Commit();
            }
            catch (Exception e) {
                tx.Rollback();
                NHibernateHelper.DestroySession();

                return Json (new { status = "error" });
            }
        }

... ... 但是这总是抛出一个System.InvalidCastException:无法在/ Users中的NpgsqlTypes.NpgsqlTypesHelper + c_ Iterator11。&lt;&gt; m _C(System.Object timestamp)[0x00000]中从源类型转换为目标类型/fxjr/Desenvolvimento/ProjetosOpenSource/Npgsql/NpgsqlSourceRelease/Npgsql2/src/NpgsqlTypes/NpgsqlTypesHelper.cs:608

我做错了什么?我在Mono 2.10.5中使用.NET 4,即使在Windows,NHibernate 3.2和Npgsql 2.0.11.91上也是如此。我也使用postgresql 9.1.1,但我已将ansi_conforming_strings设置为OFF以确保我的Nhibernate方言仍然有效。有关更多信息,更新其他类型的对象时会发生同样的事情。

我已经在nhusers列表中发布了这个,并且收到了一个非常好的建议,即尝试使用不同的数据库来检查它是否是Npgsql的错误。但是,我现在没有时间,因为我开始认为这是我的错,而不是别人的,我想我会在这里发布这个,然后在另一个数据库中重新创建我的数据库模式并尝试此代码在里面。我有点绝望,因为时间对我来说已经不多了..有人可以救我这个吗?

提前致谢。

1 个答案:

答案 0 :(得分:3)

很长一段时间后,我想我应该回到这里回答我自己的问题 这不一定是NHibernate或Npgsql中的错误 我在映射文件中犯了一个大错误,通过将同一列映射两次。这意味着在我的映射类中使用int? eventidEvent Event都映射到同一列会产生问题,因为NHibernate无法处理这个问题,即你必须选择其中一个。会发生什么是NHibernate生成的查询参数多于表中实际列数。在MS SQL Server中,更容易理解抛出的异常:

  

此SqlParameterCollection的索引N无效,Count = N

另一种选择是映射两者,但在其中一个中设置insert =“false”和update =“false”,尽管这几乎没有用。
我想很多像我这样的人(来自LINQ-TO-SQL)会尝试同样的壮举,以后会遇到很多麻烦。可悲的是,在NHibernate的文档中我没有找到任何强调这一点的东西。

希望它有所帮助。