Поставлено в тупик: настраиваемое управление сеансом NHibernate дает исключение «Указанное приведение неверно» (C #) - PullRequest
0 голосов
/ 04 октября 2011

Я пытаюсь реализовать правильное управление сессиями NHibernate в своем консольном приложении, но сталкиваюсь с некоторыми очень странными проблемами. В один момент все кажется работающим нормально, но случайно, внезапно, он начинает выдавать исключение «Указанное приведение недопустимо» при попытке извлечь конкретный объект, который, кажется, указывает на значение даты и времени, но больше информации нет предоставлена.

Теперь я исключил возможность того, что что-то не так с моими отображениями, потому что я просто закомментировал все поля, кроме строкового поля и первичного ключа (который является GUID). Исключение продолжает быть брошенным тем не менее. Кроме того, рассматриваемый объект не содержит дочерних объектов.

Вместо этого я подозреваю, что что-то не так с тем, как я вызываю свою Сессию, поэтому в кеше Сессии есть что-то, вызывающее эту проблему по какой-то туманной причине.

Я использую этот класс Util для управления сессиями:

public static class FcoNHibernateUtil
{
    private static readonly ISessionFactory sessionFactory = BuildSessionFactory();

    private static ISessionFactory BuildSessionFactory()
    {
        try
        {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration()
                .Configure()
                .AddAssembly("FcoPersistence")
                .AddAssembly("FcoLib")
                .AddAssembly("FargoLib")
                .BuildSessionFactory();
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }

    public static ISessionFactory GetSessionFactory() 
    {
        return sessionFactory;
    }

    public static ISession GetCurrentSession()
    {
        if (!CurrentSessionContext.HasBind(GetSessionFactory()))
            CurrentSessionContext.Bind(GetSessionFactory().OpenSession());

        return GetSessionFactory().GetCurrentSession();
    }

    public static void DisposeCurrentSession()
    {
        ISession currentSession = CurrentSessionContext.Unbind(GetSessionFactory());

        if (currentSession != null)
        {
            currentSession.Close();
            currentSession.Dispose();
        }
    }
}

Таким образом, в начале каждой операции моих классов DataObjectManager я получаю сеанс от общего метода, унаследованного от суперкласса, который выбирает сеанс следующим образом:

    public ISession GetSession()
    {
        return FcoNHibernateUtil.GetCurrentSession();   
    }

Когда все операции в одном цикле консольного приложения (или модульного теста) выполнены, я удостоверяюсь, что вызывается метод DisposeCurrentSession.

Есть ли что-нибудь, что может быть улучшено, что может помешать появлению этих исключений?


РЕДАКТИРОВАТЬ

Это трассировка стека:

 at NHibernate.Type.DateTimeType.IsEqual(Object x, Object y) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\DateTimeType.cs:line 93
 at NHibernate.Type.NullableType.IsEqual(Object x, Object y, EntityMode entityMode) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\NullableType.cs:line 368
 at NHibernate.Type.AbstractType.IsSame(Object x, Object y, EntityMode entityMode) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\AbstractType.cs:line 218
 at NHibernate.Type.AbstractType.IsDirty(Object old, Object current, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\AbstractType.cs:line 110
 at NHibernate.Type.NullableType.IsDirty(Object old, Object current, Boolean[] checkable, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\NullableType.cs:line 338
 at NHibernate.Type.TypeHelper.FindDirty(StandardProperty[] properties, Object[] currentState, Object[] previousState, Boolean[][] includeColumns, Boolean anyUninitializedProperties, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Type\TypeHelper.cs:line 227
 at NHibernate.Persister.Entity.AbstractEntityPersister.FindDirty(Object[] currentState, Object[] previousState, Object entity, ISessionImplementor session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 3555
 at NHibernate.Event.Default.DefaultFlushEntityEventListener.DirtyCheck(FlushEntityEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEntityEventListener.cs:line 456
 at NHibernate.Event.Default.DefaultFlushEntityEventListener.IsUpdateNecessary(FlushEntityEvent event, Boolean mightBeDirty) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEntityEventListener.cs:line 187
 at NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEntityEventListener.cs:line 43
 at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities(FlushEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 161
 at NHibernate.Event.Default.AbstractFlushingEventListener.FlushEverythingToExecutions(FlushEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 60
 at NHibernate.Event.Default.DefaultAutoFlushEventListener.OnAutoFlush(AutoFlushEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultAutoFlushEventListener.cs:line 30
 at NHibernate.Impl.SessionImpl.AutoFlushIfRequired(ISet`1 querySpaces) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 1145
 at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 1903
 at NHibernate.Impl.CriteriaImpl.List(IList results) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\CriteriaImpl.cs:line 265
 at NHibernate.Impl.CriteriaImpl.List[T]() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\CriteriaImpl.cs:line 276
 at FcoPersistence.GlobalLoginSettingsManager.GetGlobalLoginSettings(String ownIdent) in C:\Users\steemfe1\Documents\Work\Code\Epimetheus\branches\Refactoring\FcoPersistence\GlobalLoginSettingsManager.cs:line 189

И метод, где это происходит:

    public GlobalLoginSettings GetGlobalLoginSettings(string ownIdent)
    {
        session = GetSession();//if(session == null) session = Factory.OpenSession();
        ITransaction tx = session.BeginTransaction();

        GlobalLoginSettings owner;

        try
        {
            ICriteria criteria = session.CreateCriteria(typeof (GlobalLoginSettings));

            criteria.Add(Restrictions.Eq("OWNIdent", ownIdent));

            var owners = criteria.List<GlobalLoginSettings>();  //<--- exception thrown

            tx.Commit();

            owner = owners.Count > 0 ? owners[0] : null;
        }
        catch (Exception e)
        {
            tx.Rollback();
            throw e;
        }
        return owner;
    }

EDIT2:

Я получаю одну подсказку, и это происходит, когда сеанс автоматически сбрасывается при получении объекта. Таким образом, похоже, что ошибка происходит на объектах, которые находились в сеансе из предыдущих транзакций, но еще не были сброшены. Таким образом, проблема скрывается в сессии, пока она не будет использована снова.

Ответы [ 2 ]

0 голосов
/ 09 января 2012

Я прибегаю не к повторному использованию Session, а к SessionFactory. Это помогло.

0 голосов
/ 04 октября 2011

Самый простой способ - извлечь источник NHibernate куда-нибудь, указать на него Visual Studio и проверить, какое значение выдает исключение при приведении к DateTime. Затем выполните несколько шагов в стеке вызовов, чтобы найти объект, в котором находится значение. Таким образом, вы сможете найти ошибку.

...