我有一个MVC5应用程序并将我的hibernate设置为:
public class PersistenceInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
//Nhibernate session factory
Component.For<ISessionFactory>().UsingFactoryMethod(CreateNhSessionFactory).LifeStyle.Singleton,
Component.For<ISession>().UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession()).LifestylePerWebRequest(),
//All repoistories
Classes.FromAssembly(Assembly.GetAssembly(typeof(HdtRepository))).InSameNamespaceAs<HdtRepository>().WithService.DefaultInterfaces().LifestyleTransient()
);
}
我的基础知识库看起来像这样:
public abstract class RepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : Entity<TPrimaryKey>
{
/// <summary>
/// Gets the NHibernate session object to perform database operations.
/// </summary>
public ISession Session { get; set; }
/// <summary>
/// Used to get a IQueryable that is used to retrive object from entire table.
/// </summary>
/// <returns>IQueryable to be used to select entities from database</returns>
public IQueryable<TEntity> GetAll()
{
return Session.Query<TEntity>();
}
/// <summary>
/// Gets an entity.
/// </summary>
/// <param name="key">Primary key of the entity to get</param>
/// <returns>Entity</returns>
public TEntity Get(TPrimaryKey key)
{
return Session.Get<TEntity>(key);
}
/// <summary>
/// Inserts a new entity.
/// </summary>
/// <param name="entity">Entity</param>
public void Insert(TEntity entity)
{
Session.Save(entity);
}
/// <summary>
/// Updates an existing entity.
/// </summary>
/// <param name="entity">Entity</param>
public void Update(TEntity entity)
{
Session.Update(entity);
}
/// <summary>
/// Deletes an entity.
/// </summary>
/// <param name="id">Id of the entity</param>
public void Delete(TPrimaryKey id)
{
Session.Delete(Session.Load<TEntity>(id));
}
}
插入实体时,一切正常。 当我向我的Update方法添加Session.Flush()时,更新是onyl工作。
这是从Ajax调用并执行插入或更新的方法。
[Authorize]
[ValidateInput(false)]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public JsonNetResult CreateOrUpdateTimeRecord(TimeRecord tr)
{
TimeRecord trLocal;
if (tr.Id == -1 || tr.Id == 0)
{
trLocal = new TimeRecord();
trLocal.Description = tr.Description;
trLocal.StartTime = tr.StartTime;
trLocal.EndTime = tr.EndTime;
trLocal.User = _userRepo.Get(tr.User.Id);
trLocal.Hdt = _hdtRepo.Get(tr.Hdt.Id);
_timeRepo.Insert(trLocal);
}
else
{
trLocal = _timeRepo.Get(tr.Id);
trLocal.Description = tr.Description;
trLocal.StartTime = tr.StartTime;
trLocal.EndTime = tr.EndTime;
_timeRepo.Update(trLocal);
}
return new JsonNetResult() { Data = trLocal};
}
我不明白为什么这适用于插入而不适用于更新。 我是否需要关心交易和开启/关闭会话? 我认为“LifestylePerWebRequest”会为我做这件事。
干杯, 斯蒂芬
答案 0 :(得分:1)
:编辑:(我最初的回答是部分错误的)
你实现应该工作正常(只是测试它)。 虽然我可以重现更新未刷新的行为,尽管会话对象被正确放置
LifestylePerWebRequest
实际上处理好了,它会在请求结束时处理会话。因此你必须将请求句柄添加到web.config等...所以windsor的东西完全知道ISession是一次性的,它必须处理它......
这是因为会话的FlushMode。
默认模式是自动,这可能不是您想要的,因为您不能依赖存储的更改(特别是使用更新调用)。
您可以更改已创建的会话对象的FlushMode,或者,这是我推荐的,使用事务。
让我们看看下面的例子:
var session = container.Resolve<ISession>();
var obj = new Paper()
{
Author = "Author",
Description = "Description",
};
session.Save(obj);
obj.Author = "Author2";
session.Update(obj);
在这种情况下,更新永远不会刷新/存储在数据库中。这就是我猜你现在的行为。
现在让我们在它周围添加一个交易:
var session = container.Resolve<ISession>();
using (var transaction = session.BeginTransaction())
{
var obj = new Paper()
{
Author = "Author",
Description = "Description",
};
session.Save(obj);
obj.Author = "Author2";
session.Update(obj);
transaction.Commit();
}
现在可以保存更改。