NHibernate的:System.Argument例外:具有相同的密钥项目已被添加 [英] NHibernate: System.Argument Exception : An item with the same key has already been added

查看:119
本文介绍了NHibernate的:System.Argument例外:具有相同的密钥项目已被添加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到一个很难重现的零星的错误。我的第一个猜测是,我有一个泄漏的nhibernate会话,但是当我运行 nhibernate分析器时,我没有看到很不同寻常。


  • MVC 2.0

  • Fluent version 1.1.0.685

  • NHibernate版本2.1.2.4000


$ b


异常:System.ArgumentException:
具有相同键的项目已经添加了



堆栈跟踪:在
System.Collections.Generic.Dictionary <$ c
NHibernate.Util.ThreadSafeDictionary 2.Add(TKey
key,TValue value
key,TValue value,Boolean add) )
NHibernate.SqlTypes.SqlTypeFactory.GetTypeWithLen [T](Int32
length,TypeWithLenCreateDelegate
createDelegate)at
NHibernate.Type.EnumStringType..ctor(Type
enumClass,Int32长度)

我正在使用存储库模型。这是我的资源库类。

  public sealed class Repository< T> :IRepository< T>其中T:CoreObjectBase 
{
#region IRepository< T>成员

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

public IQueryable< T> GetAll()
{
return(来自Session.Linq< T>()中的实体select实体);
}

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

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

entity.Validate();

Session.SaveOrUpdate(entities [x]);

if(x == entities.Count() - 1 ||(x!= 0&& x%20 == 0))// 20是批量大小
{
Session.Flush();
Session.Clear();
}
}
tx.Commit();


$ b $ public void SaveWithDependence< K>(T entity,K dependent)其中K:CoreObjectBase
{
entity.Validate();
dependant.Validate();

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


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

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


$ b $ public void删除(T实体)
{
using(ITransaction tx = Session.BeginTransaction())
{
Session.Delete(entity);
tx.Commit();


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

返回结果;

// return query.SatisfyingElementFrom(Session.Linq< T>());
}

public IQueryable< T> GetList(QueryBase< T> query)
{
return query.SatisfyingElementsFrom(Session.Linq< T>
}

///< summary>
///从一级缓存中删除特定对象,以便从数据库中刷新
///< / summary>
///< param name =entity>< / param>
public void Evict(T entity)
{
Session.Evict(entity);
}
#endregion
}

这里是我的会话助手,改编自

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

public ISession GetSession()
{
ISessionFactory factory = getSessionFactory();
ISession session = getExistingOrNewSession(factory);
返回会话;

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

return _sessionFactory;

$ b $ private ISessionFactory BuildSessionFactory()
{
return Fluentntly.Configure()。Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005
.ConnectionString(c => c
.FromConnectionStringWithKey(MyDatabase))
.AdoNetBatchSize(20))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf< SessionHelper>())
.BuildSessionFactory();

$ b $ 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);
}

返回会话;


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

return _currentSession;

$ b $ public ISession GetExistingWebSession()
{
返回HttpContext.Current.Items [GetType()。FullName]作为ISession;

$ b $ private ISession openSessionAndAddToContext(ISessionFactory factory)
{
ISession session = factory.OpenSession();
HttpContext.Current.Items.Remove(GetType()。FullName);
HttpContext.Current.Items.Add(GetType()。FullName,session);
返回会话;




$ b $ p $任何想法或建议,以避免这个问题?解决方案问题是, SessionHelper 不是线程安全的。它可能会建立几个会话工厂(这是一个不好的Singleton实现),这反过来可能会导致你看到的错误。



我推荐使用

I'm getting a sporadic error that is difficult to reproduce. My first guess is that somehow I have a leaking nhibernate session, however when I ran the nhibernate profiler, I didn't see much out of the ordinary.

  • MVC 2.0
  • Fluent version 1.1.0.685
  • NHibernate version 2.1.2.4000

Exception: System.ArgumentException : An item with the same key has already been added.

Stack Trace: at System.Collections.Generic.Dictionary2.Insert(TKey key, TValue value, Boolean add) at NHibernate.Util.ThreadSafeDictionary2.Add(TKey key, TValue value) at NHibernate.SqlTypes.SqlTypeFactory.GetTypeWithLen[T](Int32 length, TypeWithLenCreateDelegate createDelegate) at NHibernate.Type.EnumStringType..ctor(Type enumClass, Int32 length)

I am using a repository model. Here's my repository class.

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

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

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

    public T GetById(int id)
    {
        return Session.Get<T>(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<K>(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<T> query)
    {
        var result = query.SatisfyingElementFrom(Session.Linq<T>());

        return result;

        //return query.SatisfyingElementFrom(Session.Linq<T>());
    }

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

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

And here is my session helper, adapted from 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<SessionHelper>())
                .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;
    }
}

Any ideas or suggestions to avoid this issue?

解决方案

Problem is, that SessionHelper isn't thread-safe. It will potentially build several session factories (it's a bad implementation of Singleton), which in turn probably causes the error you're seeing.

I recommend using SharpArchitecture as guidance instead.

这篇关于NHibernate的:System.Argument例外:具有相同的密钥项目已被添加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆