保留与NH会话不相关的Castle DynamicProxy [英] Persisting a Castle DynamicProxy that's not associated with a NH Session
问题描述
我的会话使用NHInterceptor向模型添加INotifyPropertyChanged支持.
My session uses an NHInterceptor to add INotifyPropertyChanged support to models.
// 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创建可添加更改通知功能的代理.这意味着所有我的对象都来自数据库,作为城堡代理,它们是AFAIK透明的.
The ProxyFactory uses Castle to create proxies that add change notification functionality. That means all my objects come from the DB as Castle Proxies, which are AFAIK transparent.
每当我将这些NH生成的MVVM代理之一传递给Session.Save()
时,一切都很好.
Whenever I pass one of those NH Generated MVVM-proxies into Session.Save()
, all's fine.
现在,随着数据驱动的应用程序的发展,我还需要创建新实例并保存它们.我可以创建模型类型的实例,然后通过会话保存它们.创建MVVM代理实例(使用Ninject确保整个使用相同的SessionFactory和ProxyFactory实例)并将其扔到Session.Save()
中将导致以下结果:
Now, as data driven Applications go, I also need to create new instances and save them. I can create instances of the model type and save them via the session all right. Creating a MVVM proxy instance (using Ninject to ensure that the same SessionFactory and ProxyFactory instances are used all over) and throwing this into Session.Save()
results in the following:
"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:
有什么想法在这里出了什么问题(或者我可能忘记了什么)?
Any ideas what goes wrong here (or what I might have forgotten)?
现在可以正常工作了,但是为什么必须在外部创建的实例的拦截器中添加识别逻辑(请参见下面的代码),而在内部创建的实例却可以原样保留呢?
EDIT : Now got it working, but why do I have to add recognition logic (see code below) to the interceptor for instances created outside, while instances created inside can be persisted as the are?
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);
}
推荐答案
实现GetEntityName方法可以解决问题.
Implementing the GetEntityName method did the trick.
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);
}
这篇关于保留与NH会话不相关的Castle DynamicProxy的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!