C# 如何在NHibernate中自动更新行并插入新行,只需调用一次保存?
假设我有一个II型SCD数据库,基本上是只附加的。我正在使用NHibernate将对象持久化到我的数据库中。我有一个这样的目标:C# 如何在NHibernate中自动更新行并插入新行,只需调用一次保存?,c#,nhibernate,versioning,C#,Nhibernate,Versioning,假设我有一个II型SCD数据库,基本上是只附加的。我正在使用NHibernate将对象持久化到我的数据库中。我有一个这样的目标: Pony |- int Id |- Guid EntityId |- string PonyName |- string PonyColor |- int RevisionValidFrom |- int RevisionValidTo 下面是一个典型的场景: Pony myLittlePony = myStable.GetLatestPonyByGuid("0f1
Pony
|- int Id
|- Guid EntityId
|- string PonyName
|- string PonyColor
|- int RevisionValidFrom
|- int RevisionValidTo
下面是一个典型的场景:
Pony myLittlePony = myStable.GetLatestPonyByGuid("0f1ac08a-3328-43db-b278-77c272e4fea3");
myLittlePony.PonyColor = "Fish";
myNHSession.Save(myLittlePony);
我希望能够调用
Session.Save(myLittlePony)
,并让NHibernate将旧实体的RevisionValidTo
更新到我指定的任何位置,然后将修改后的小马
插入一个具有新Id
的新行,基本上就像是一个全新的对象被持久化到数据库中一样。这可以用来完成。这可以用来完成。我最终创建了自己的SaveOrUpdateEventListener,并将其注册到NHibernate的配置中。然后发出原始SQL命令
对于NHibernate配置:
var listener = new PonySaveOrUpdateEventListener();
config.SetListener(NHibernate.Event.ListenerType.SaveUpdate, listener);
config.SetListener(NHibernate.Event.ListenerType.Save, listener);
班级:
public class PonySaveOrUpdateEventListener : DefaultSaveOrUpdateEventListener
{
protected override object EntityIsPersistent(SaveOrUpdateEvent @event)
{
Pony ent = @event.Entity as Pony;
// I don't care if it's not a pony or if the entity doesn't need updating, call base!
if (ent == null || !IsDirty(@event))
return base.EntityIsPersistent(@event);
// Do nasty dialect-specific raw SQL because using NH to update this row throws us into an infinite loop
string tablename = ((ILockable)@event.Entry.Persister).RootTableName.ToLower();
System.Data.IDbCommand command = ((ISession)@event.Session).Connection.CreateCommand();
command.CommandText = String.Format("update {0} set RevisionValidTo = {1} where Id = '{2}'", tablename, CurrentRevision.Id, ent.Id);
command.ExecuteNonQuery();
// Make the event look like it was never persistent and force a transient insert of the entity
ent.Id = Guid.Empty;
@event.Entry = null;
return EntityIsTransient(@event);
}
protected override object EntityIsTransient(SaveOrUpdateEvent @event)
{
Pony ent = @event.Entity as Pony;
if (ent == null)
return base.EntityIsTransient(@event);
ent.RevisionValidFrom = Host.NextRevision;
ent.RevisionValidTo = null;
return base.EntityIsTransient(@event);
}
private static bool IsDirty(SaveOrUpdateEvent @event)
{
IEntityPersister persister = @event.Entry.Persister;
object[] oldState = @event.Entry.LoadedState;
object[] currentState = persister.GetPropertyValues(@event.Entity, @event.Session.EntityMode);
Int32[] dirtyProps = persister.FindDirty(currentState, oldState, @event.Entity, @event.Session);
return dirtyProps != null;
}
}
我最终创建了自己的SaveOrUpdateEventListener,并将其注册到NHibernate的配置中。然后发出原始SQL命令 对于NHibernate配置:
var listener = new PonySaveOrUpdateEventListener();
config.SetListener(NHibernate.Event.ListenerType.SaveUpdate, listener);
config.SetListener(NHibernate.Event.ListenerType.Save, listener);
班级:
public class PonySaveOrUpdateEventListener : DefaultSaveOrUpdateEventListener
{
protected override object EntityIsPersistent(SaveOrUpdateEvent @event)
{
Pony ent = @event.Entity as Pony;
// I don't care if it's not a pony or if the entity doesn't need updating, call base!
if (ent == null || !IsDirty(@event))
return base.EntityIsPersistent(@event);
// Do nasty dialect-specific raw SQL because using NH to update this row throws us into an infinite loop
string tablename = ((ILockable)@event.Entry.Persister).RootTableName.ToLower();
System.Data.IDbCommand command = ((ISession)@event.Session).Connection.CreateCommand();
command.CommandText = String.Format("update {0} set RevisionValidTo = {1} where Id = '{2}'", tablename, CurrentRevision.Id, ent.Id);
command.ExecuteNonQuery();
// Make the event look like it was never persistent and force a transient insert of the entity
ent.Id = Guid.Empty;
@event.Entry = null;
return EntityIsTransient(@event);
}
protected override object EntityIsTransient(SaveOrUpdateEvent @event)
{
Pony ent = @event.Entity as Pony;
if (ent == null)
return base.EntityIsTransient(@event);
ent.RevisionValidFrom = Host.NextRevision;
ent.RevisionValidTo = null;
return base.EntityIsTransient(@event);
}
private static bool IsDirty(SaveOrUpdateEvent @event)
{
IEntityPersister persister = @event.Entry.Persister;
object[] oldState = @event.Entry.LoadedState;
object[] currentState = persister.GetPropertyValues(@event.Entity, @event.Session.EntityMode);
Int32[] dirtyProps = persister.FindDirty(currentState, oldState, @event.Entity, @event.Session);
return dirtyProps != null;
}
}
ISession.SaveOrUpdate()方法没有完成任务吗?ISession.SaveOrUpdate()方法没有完成任务吗?