NHibernate: System.Argument Exception : Элемент с таким же ключом уже был добавлен

Я получаю спорадическую ошибку, которую трудно воспроизвести. Мое первое предположение заключается в том, что у меня каким-то образом протекает сеанс nhibernate, Товар с таким же ключом уже добавлено.

Stack Trace: at System.Collections.Generic.Dictionary 2.Insert (TKey ключ, значение TValue, логическое сложение) в NHibernate.Util.ThreadSafeDictionary 2. Добавить (TKey ключ, значение TValue) при NHibernate.SqlTypes.SqlTypeFactory.GetTypeWithLen [T] (Int32 длина, TypeWithLenCreateDelegate createDelegate) в NHibernate.Type.EnumStringType..ctor (Тип enumClass, длина Int32)

Я использую модель репозитория. Вот мой класс репозитория.

public sealed class Repository : IRepository where T : CoreObjectBase
{
    #region IRepository Members

    private ISession Session
    {
        get
        {
            return new SessionHelper().GetSession();
        }
    }

    public IQueryable GetAll()
    {
        return (from entity in Session.Linq() select entity);
    }

    public T GetById(int id)
    {
        return Session.Get(id);
    }

    public void Save(params T[] entities)
    {
        using (ITransaction tx = Session.BeginTransaction())
        {
            for (int x = 0; x < entities.Count(); x++)
            {
                var entity = entities[x];

                entity.Validate();

                Session.SaveOrUpdate(entities[x]);

                if (x == entities.Count() - 1 || (x != 0 && x % 20 == 0)) //20 is the batch size
                {
                    Session.Flush();
                    Session.Clear();
                }
            }
            tx.Commit();
        }
    }

    public void SaveWithDependence(T entity, K dependant) where K : CoreObjectBase
    {
        entity.Validate();
        dependant.Validate();

        using (ITransaction tx = Session.BeginTransaction())
        {
            Session.SaveOrUpdate(entity);
            Session.SaveOrUpdate(dependant);
            tx.Commit();
        }
    }

    public void Save(T entity)
    {
        entity.Validate();

        using (ITransaction tx = Session.BeginTransaction())
        {
            Session.SaveOrUpdate(entity);
            tx.Commit();
        }
    }

    public void Delete(T entity)
    {
        using (ITransaction tx = Session.BeginTransaction())
        {
            Session.Delete(entity);
            tx.Commit();
        }
    }

    public T GetOne(QueryBase query)
    {
        var result = query.SatisfyingElementFrom(Session.Linq());

        return result;

        //return query.SatisfyingElementFrom(Session.Linq());
    }

    public IQueryable GetList(QueryBase query)
    {
        return query.SatisfyingElementsFrom(Session.Linq());
    }

    /// 
    /// remove the sepcific object from level 1 cache so it can be refreshed from the database
    /// 
    /// 
    public void Evict(T entity)
    {
        Session.Evict(entity);
    }
    #endregion
}

А вот мой помощник сеанса, адаптированный из this .

public sealed class SessionHelper
{
    private static ISessionFactory _sessionFactory;
    private static ISession _currentSession;

    public ISession GetSession()
    {
        ISessionFactory factory = getSessionFactory();
        ISession session = getExistingOrNewSession(factory);
        return session;
    }

    private ISessionFactory getSessionFactory()
    {
        if (_sessionFactory == null)
        {
            _sessionFactory = BuildSessionFactory();
        }

        return _sessionFactory;
    }

    private ISessionFactory BuildSessionFactory()
    {
        return Fluently.Configure().Database(
            FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005
                .ConnectionString(c => c
                    .FromConnectionStringWithKey("MyDatabase"))
                    .AdoNetBatchSize(20))
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf())
                .BuildSessionFactory();
    }

    private ISession getExistingOrNewSession(ISessionFactory factory)
    {
        if (HttpContext.Current != null)
        {
            ISession session = GetExistingWebSession();
            if (session == null)
            {
                session = openSessionAndAddToContext(factory);
            }
            else if (!session.IsOpen)
            {
                session = openSessionAndAddToContext(factory);
            }

            return session;
        }

        if (_currentSession == null)
        {
            _currentSession = factory.OpenSession();
        }
        else if (!_currentSession.IsOpen)
        {
            _currentSession = factory.OpenSession();
        }

        return _currentSession;
    }

    public ISession GetExistingWebSession()
    {
        return HttpContext.Current.Items[GetType().FullName] as ISession;
    }

    private ISession openSessionAndAddToContext(ISessionFactory factory)
    {
        ISession session = factory.OpenSession();
        HttpContext.Current.Items.Remove(GetType().FullName);
        HttpContext.Current.Items.Add(GetType().FullName, session);
        return session;
    }
}

Есть идеи или предложения, чтобы избежать этой проблемы?

7
задан Josh 31 January 2011 в 19:31
поделиться