Я получаю спорадическую ошибку, которую трудно воспроизвести. Мое первое предположение заключается в том, что у меня каким-то образом протекает сеанс 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;
}
}
Есть идеи или предложения, чтобы избежать этой проблемы?