如何关闭NHibernate';s自动(脏检查)更新行为?
我刚刚发现,如果我从NHibernate会话中获取一个对象并更改该对象的属性,NHibernate将在提交时自动更新该对象,而无需调用如何关闭NHibernate';s自动(脏检查)更新行为?,nhibernate,Nhibernate,我刚刚发现,如果我从NHibernate会话中获取一个对象并更改该对象的属性,NHibernate将在提交时自动更新该对象,而无需调用会话。更新(myObj) 我可以看出这是多么有用,但作为默认行为,它似乎疯狂 更新:我现在理解了持久性无知,因此这种行为现在显然是首选。我将把这个现在令人尴尬的问题留在这里,希望能帮助其他亵渎者 我怎样才能阻止这种事情发生?这是默认的NHibernate行为还是来自Fluent NHibernate的AutoPersistenceModel 如果没有办法阻止,我该
会话。更新(myObj)
我可以看出这是多么有用,但作为默认行为,它似乎疯狂
更新:我现在理解了持久性无知,因此这种行为现在显然是首选。我将把这个现在令人尴尬的问题留在这里,希望能帮助其他亵渎者
我怎样才能阻止这种事情发生?这是默认的NHibernate行为还是来自Fluent NHibernate的AutoPersistenceModel
如果没有办法阻止,我该怎么办?除非我没有抓住要点,否则这种行为似乎会造成一种混乱
我正在使用NHibernate 2.0.1.4和2009年3月18日的流畅NHibernate构建
这家伙对吗
我还读过,重写事件侦听器可能是解决这个问题的一个方法。但是,在这种情况下,不会调用IDirtyCheckEventListener.OnDirtyCheck。有人知道我需要覆盖哪个侦听器吗?您可以将
会话.FlushMode
设置为FlushMode.Never
。这将使您的操作更加明确
ie:ontx.Commit()
或session.Flush()
。当然,这仍然会在提交/刷新时更新数据库。如果您不希望出现这种行为,那么调用session.execute(yourObj)
,它将变为瞬态,NHibernate将不会为其发出任何db命令
对编辑的响应:是的,那个家伙给了你更多控制它的选项。调用SaveOrUpdate()或Save()会使对象持久化。如果您使用ISession或从对持久对象的引用检索到它,那么该对象是持久的,刷新会话将保存更改。您可以通过对对象调用execute()来防止这种行为,从而使其成为瞬态对象
编辑补充:我一般认为一个单位是一个工作单位。这很容易在web应用程序中实现。使用每个请求的会话,但在WinForms中需要更多控制。我的解决方案:
我们通过在NH中使用事件监听器实现了这一点(这不是我的工作-但我找不到我在哪里做的链接…) 我们有一个EventListener,用于在读取数据时将其设置为只读,然后有一个用于Save(和SaveOrUpdate)将其设置为已加载,这样当我们手动调用对象上的
Save()
时,该对象将保持不变
或者您可以使用没有状态/变更跟踪的IStatelessSession
这将在加载时立即将实体/项设置为只读
我只包含了一个插入事件侦听器,但我的配置代码引用了所有这些侦听器
//
///加载对象后,侦听器会将其状态更改为只读,以便
///NH不会自动保存它
///
///
///要保存此对象,将使用SaveUpdateEventListener。
///
公共类PostLoadEventListener:IPostLoadEventListener
{
PostLoad上的公共无效(PostLoadEvent@event)
{
EntityEntry=@event.Session.PersistenceContext.GetEntry(@event.Entity);
entry.BackSetStatus(Status.ReadOnly);
}
}
保存对象时,我们调用此函数将该对象设置为已加载(这意味着它现在将保持不变)
公共类SaveUpdateEventListener:ISaveOrUpdateEventListener
{
public static readonly CascadingAction ResetReadOnly=new ResetReadOnlyCascadeAction();
///
///将任何已加载项的状态更改为只读。
///
///
///更改所有已加载实体的状态,以便NH不再跟踪这些实体上的更改。
///
SaveOrUpdate(SaveOrUpdateEvent@event)上的公共无效
{
var session=@event.session;
EntityEntry=session.PersistenceContext.GetEntry(@event.Entity);
if(entry!=null&&entry.Persister.IsMutable&&entry.Status==Status.ReadOnly)
{
条目.返回状态(状态.已加载);
cascadeoUpdate(@event,entry.Persister,@event.entry);
}
}
私有静态void cascadeUpdate(SaveOrUpdateEvent@event,ientTypersister EntityPerister,
对象实体(entityEntry)
{
IEventSource=@event.Session;
source.PersistenceContext.IncrementCascadeLevel();
尝试
{
新的级联(ResetReadOnly,CascadePoint.BeforeFlush,source).CascadeOn(entityPersister,entityEntry);
}
最后
{
source.PersistenceContext.DecrementScadelevel();
}
}
}
我们将其实施到NH中,因此:
public static ISessionFactory CreateSessionFactory(IPersistenceConfigurer dbConfig, Action<MappingConfiguration> mappingConfig, bool enabledChangeTracking,bool enabledAuditing, int queryTimeout)
{
return Fluently.Configure()
.Database(dbConfig)
.Mappings(mappingConfig)
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<__AuditEntity>())
.ExposeConfiguration(x => Configure(x, enabledChangeTracking, enabledAuditing,queryTimeout))
.BuildSessionFactory();
}
/// <summary>
/// Configures the specified config.
/// </summary>
/// <param name="config">The config.</param>
/// <param name="enableChangeTracking">if set to <c>true</c> [enable change tracking].</param>
/// <param name="queryTimeOut">The query time out in minutes.</param>
private static void Configure(NHibernate.Cfg.Configuration config, bool enableChangeTracking, bool enableAuditing, int queryTimeOut)
{
config.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlKeyWords, "none");
if (queryTimeOut > 0)
{
config.SetProperty("command_timeout", (TimeSpan.FromMinutes(queryTimeOut).TotalSeconds).ToString());
}
if (!enableChangeTracking)
{
config.AppendListeners(NHibernate.Event.ListenerType.PostLoad, new[] { new Enact.Core.DB.NHib.Listeners.PostLoadEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.SaveUpdate, new[] { new Enact.Core.DB.NHib.Listeners.SaveUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostUpdate, new[] { new Enact.Core.DB.NHib.Listeners.PostUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostInsert, new[] { new Enact.Core.DB.NHib.Listeners.PostInsertEventListener() });
}
}
公共静态ISessionFactory CreateSessionFactory(IPersistenceConfiger数据库配置、动作映射配置、bool启用的变更跟踪、bool启用的数据编辑、int queryTimeout)
{
流畅地返回。Configure()
.Database(dbConfig)
.Mappings(mappingConfig)
.Mappings(x=>x.FluentMappings.AddFromAssemblyOf())
.ExposeConfiguration(x=>Configure(x,enabledChangeTracking,enabledAuditing,queryTimeout))
.BuildSessionFactory();
}
///
///配置指定的配置。
///
///配置。
///如果设置为true[启用更改跟踪]。
///查询超时(分钟)。
私有静态无效配置(NHibernate.Cfg.Configuration config,bool enableChangeTracking,bool ena
public class SaveUpdateEventListener : ISaveOrUpdateEventListener
{
public static readonly CascadingAction ResetReadOnly = new ResetReadOnlyCascadeAction();
/// <summary>
/// Changes the status of any loaded item to ReadOnly.
/// </summary>
/// <remarks>
/// Changes the status of all loaded entities, so that NH will no longer TrackChanges on them.
/// </remarks>
public void OnSaveOrUpdate(SaveOrUpdateEvent @event)
{
var session = @event.Session;
EntityEntry entry = session.PersistenceContext.GetEntry(@event.Entity);
if (entry != null && entry.Persister.IsMutable && entry.Status == Status.ReadOnly)
{
entry.BackSetStatus(Status.Loaded);
CascadeOnUpdate(@event, entry.Persister, @event.Entry);
}
}
private static void CascadeOnUpdate(SaveOrUpdateEvent @event, IEntityPersister entityPersister,
object entityEntry)
{
IEventSource source = @event.Session;
source.PersistenceContext.IncrementCascadeLevel();
try
{
new Cascade(ResetReadOnly, CascadePoint.BeforeFlush, source).CascadeOn(entityPersister, entityEntry);
}
finally
{
source.PersistenceContext.DecrementCascadeLevel();
}
}
}
public static ISessionFactory CreateSessionFactory(IPersistenceConfigurer dbConfig, Action<MappingConfiguration> mappingConfig, bool enabledChangeTracking,bool enabledAuditing, int queryTimeout)
{
return Fluently.Configure()
.Database(dbConfig)
.Mappings(mappingConfig)
.Mappings(x => x.FluentMappings.AddFromAssemblyOf<__AuditEntity>())
.ExposeConfiguration(x => Configure(x, enabledChangeTracking, enabledAuditing,queryTimeout))
.BuildSessionFactory();
}
/// <summary>
/// Configures the specified config.
/// </summary>
/// <param name="config">The config.</param>
/// <param name="enableChangeTracking">if set to <c>true</c> [enable change tracking].</param>
/// <param name="queryTimeOut">The query time out in minutes.</param>
private static void Configure(NHibernate.Cfg.Configuration config, bool enableChangeTracking, bool enableAuditing, int queryTimeOut)
{
config.SetProperty(NHibernate.Cfg.Environment.Hbm2ddlKeyWords, "none");
if (queryTimeOut > 0)
{
config.SetProperty("command_timeout", (TimeSpan.FromMinutes(queryTimeOut).TotalSeconds).ToString());
}
if (!enableChangeTracking)
{
config.AppendListeners(NHibernate.Event.ListenerType.PostLoad, new[] { new Enact.Core.DB.NHib.Listeners.PostLoadEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.SaveUpdate, new[] { new Enact.Core.DB.NHib.Listeners.SaveUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostUpdate, new[] { new Enact.Core.DB.NHib.Listeners.PostUpdateEventListener() });
config.AppendListeners(NHibernate.Event.ListenerType.PostInsert, new[] { new Enact.Core.DB.NHib.Listeners.PostInsertEventListener() });
}
}