私のセッションでは、NHInterceptor を使用して INotifyPropertyChanged サポートをモデルに追加します。
// I use the session generated here to fetch Data
public class SessionServiceImpl : ISessionService
{
[Inject]
public ISessionFactory SessionFactory { get; set; }
[Inject]
public NhChangeNotificationInterceptorImpl ChangeNotificationInterceptor { get; set; }
public ISession GetSession() // reduced code here
{
return SessionFactory.OpenSession(ChangeNotificationInterceptor);
}
}
// This is the interceptor implementation
public class NhChangeNotificationInterceptorImpl : EmptyInterceptor, IInterceptor
{
[Inject]
public ISessionFactory SessionFactory { get; set; }
[Inject]
public ViewModelProxyFactory ProxyFactory { get; set; }
public override object Instantiate(string entityTypeName, EntityMode entityMode, object id)
{
Type type = Type.GetType(entityTypeName);
if (type == null) { /* Throw Exception*/ }
bool isViewModel = false;
while (type != typeof(object))
{
Type tempType = type.BaseType;
if (tempType == typeof(ViewModelBase))
{
isViewModel = true;
break;
}
}
if (entityMode == EntityMode.Poco && isViewModel)
{
var instance = ProxyFactory.CreateProxy(type);
SessionFactory.GetClassMetadata(entityTypeName).SetIdentifier(instance, id, entityMode);
return instance;
}
return base.Instantiate(entityTypeName, entityMode, id);
}
}
ProxyFactory は Castle を使用して、変更通知機能を追加するプロキシを作成します。つまり、私のすべてのオブジェクトは、知る限り透過的な Castle Proxies として DB から取得されます。
これらの NH 生成 MVVM プロキシの 1 つを に渡すとSession.Save()
、すべて問題ありません。
さて、データ ドリブン アプリケーションの進行に伴い、新しいインスタンスを作成して保存する必要もあります。モデル タイプのインスタンスを作成し、セッションを介して問題なく保存できます。MVVM プロキシ インスタンスを作成し (Ninject を使用して、同じ SessionFactory および ProxyFactory インスタンスが全体で使用されるようにします)、これをスローするSession.Save()
と、次のようになります。
"NHibernate.MappingException".
Message=No persister for: Castle.Proxies.FieldDescriptionProxy
Source=NHibernate
StackTrace:
at NHibernate.Impl.SessionFactoryImpl.GetEntityPersister(String entityName)
at NHibernate.Impl.SessionImpl.GetEntityPersister(String entityName, Object obj)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at Interpretation.UI.Service.Impl.Dao.FieldDao.SaveFields(IList`1 fields, ISession session) in C:\...\FieldDao.cs:Zeile 51.
InnerException:
ここで何がうまくいかないのか(または私が忘れていた可能性があるもの)はありますか?
編集:これで機能しましたが、内部で作成されたインスタンスはそのまま保持できるのに、外部で作成されたインスタンスのインターセプターに認識ロジック (以下のコードを参照) を追加する必要があるのはなぜですか?
public override string GetEntityName(object entity)
{
Type type = entity.GetType();
if (type.FullName.StartsWith("Castle.Proxies") &&
type.FullName.EndsWith("Proxy"))
{
return type.BaseType.FullName;
}
return base.GetEntityName(entity);
}