【发布时间】:2011-06-18 19:34:28
【问题描述】:
我遇到了一个难以重现的零星错误。我的第一个猜测是不知何故我有一个泄漏的 nhibernate 会话,但是当我运行 nhibernate profiler 时,我并没有看到太多异常。
- MVC 2.0
- Fluent 版本 1.1.0.685
- NHibernate 版本 2.1.2.4000
异常:System.ArgumentException: 具有相同密钥的项目已经 已添加。
堆栈跟踪:在 System.Collections.Generic.Dictionary
2.Insert(TKey key, TValue value, Boolean add) at NHibernate.Util.ThreadSafeDictionary2.Add(TKey 键,TValue 值)在 NHibernate.SqlTypes.SqlTypeFactory.GetTypeWithLen[T](Int32 长度,TypeWithLenCreateDelegate createDelegate) 在 NHibernate.Type.EnumStringType..ctor(类型 枚举类,Int32 长度)
我正在使用存储库模型。这是我的存储库类。
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
}
这是我的会话助手,改编自 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;
}
}
有什么想法或建议可以避免这个问题?
【问题讨论】:
-
乔希,你让你的 SessionHelper 线程安全吗?
标签: nhibernate session fluent-nhibernate