1

我面临一个显然非常奇怪的问题(我一定做错了什么,只是找不到我的错误!)。当某些 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 ();

... ...每次都可以正常工作(是的,我将很快将其包装在事务中)。

但是,稍后,以下内容永远不会起作用(这是 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: Cannot cast from source type to destination type at NpgsqlTypes.NpgsqlTypesHelper+c_ Iterator11.<>m _C (System.Object timestamp) [0x00000] in /Users/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 的错。但是,我现在没有时间这样做,因为我开始认为这是我的错,而不是别人的错,所以我想在另一个数据库中重新创建我的数据库架构并尝试这段代码之前,我会在这里发布这个在里面。我有点绝望,因为我的时间已经不多了..有人能救我吗?

提前致谢。

4

1 回答 1

3

很久之后,我想我应该回到这里来回答我自己的问题。
这不一定是 NHibernate 或 Npgsql 中的错误。
通过两次映射同一列,我在映射文件中犯了一个巨大的错误。这意味着在我的映射类中有 aint? eventid和 aEvent Event都映射到同一列会给您带来问题,因为 NHibernate 无法处理这个问题,即您必须选择其中一个。发生的情况是 NHibernate 将生成比表中的实际列数更多的参数的查询。在 MS SQL Server 中,更容易理解抛出的异常:

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

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

希望它可以帮助某人。

于 2012-04-08T14:59:59.680 回答