обновление объекта с помощью nhibernate создает исключение InvalidCastException (но сохранение его не дает) - PullRequest
1 голос
/ 09 ноября 2011

У меня очень странная проблема (я, должно быть, что-то делаю не так, просто не могу найти свои ошибки!).Когда определенные 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>

Iпроверил определение таблицы, и все типы, кажется, соответствуют определенному классу (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: Невозможно выполнить приведениеот исходного типа к целевому типу в NpgsqlTypes.NpgsqlTypesHelper + c_ Iterator11. <> m _C (отметка времени System.Object) [0x00000] в / Users / fxjr / Desenvolvimento / ProjetosOpenSource / NpgsqlsourceNNGSqSqSqSqSqSqSqSPG/NpgsqlTypes/NpgsqlTypesHelper.cs:608

Что я делаю не так?Я использую .NET 4 в Mono 2.10.5, хотя то же самое происходит в Windows, NHibernate 3.2 и Npgsql 2.0.11.91.Я также использую postgresql 9.1.1, но я установил ansi_conforming_strings в OFF, чтобы убедиться, что мой диалект Nhibernate все еще работает.Для получения дополнительной информации то же самое происходит при обновлении других типов объектов.

Я уже разместил это в списке nhusers и получил очень хорошее предложение при попытке другого db проверить, не является ли это его ошибкой Npgsql.Тем не менее, у меня нет времени на это прямо сейчас, и, поскольку я начинаю думать, что это моя вина, а не кто-то другой, я решил опубликовать это здесь, прежде чем воссоздать мою схему БД в другой базе данных и попробовать этот кодв этом.Я становлюсь немного отчаянным, так как время уходит на меня ... может кто-нибудь спасти меня на этом?

Заранее спасибо.

1 Ответ

3 голосов
/ 08 апреля 2012

Спустя долгое время я подумал, что должен вернуться сюда, чтобы ответить на свой вопрос.
Это не обязательно ошибка в NHibernate или Npgsql.
Я делал огромную ошибку в файлах отображения, отображая один и тот же столбец дважды. Это означает, что наличие int? eventid и Event Event в моем сопоставленном классе, оба сопоставления с одним и тем же столбцом, создадут вам проблемы, поскольку NHibernate не может справиться с этим, то есть вы должны выбрать один из них. Что происходит, так это то, что NHibernate будет генерировать запросы с большим количеством параметров, чем фактическое количество столбцов в вашей таблице. В MS SQL Server легче понять выброшенное исключение:

Неверный индекс N для этой SqlParameterCollection с Count = N

Другой альтернативой является сопоставление обоих, но установка insert = "false" и update = "false" в одном из них, хотя это вряд ли полезно.
Я думаю, что многие люди, подобные мне (из LINQ-TO-SQL), попытаются сделать то же самое, и у них будет много проблем в дальнейшем. К сожалению, я не нашел ничего, что подчеркивает это в документации NHibernate.

Надеюсь, это кому-нибудь поможет.

...