You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NHibernate 2.1升级至5.5后ISession.Load创建代理失败问题

NHibernate 5.5升级后ISession.Load创建代理失败问题

问题详情

从NHibernate 2.1升级至5.5版本后,应用构建运行正常,数据库实体读写无问题,但调用ISession.Load时抛出代理创建失败异常:

Creating a proxy instance failed
at NHibernate.Proxy.StaticProxyFactory.GetProxy(Object id, ISessionImplementor session)
at NHibernate.Event.Default.DefaultLoadEventListener.CreateProxyIfNecessary(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext)
at NHibernate.Event.Default.DefaultLoadEventListener.ProxyOrLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType)
at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType)
at NHibernate.Impl.SessionImpl.Load(String entityName, Object id)
at NHibernate.Impl.SessionImpl.Load[T](Object id)

INNER EXCEPTION:
Sequence contains more than one matching element
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at NHibernate.Proxy.ProxyBuilderHelper.GenerateMethodSignature(String name, MethodInfo method, TypeBuilder typeBuilder)
at NHibernate.Proxy.NHibernateProxyBuilder.ImplementCallMethodOnImplementation(TypeBuilder typeBuilder, MethodInfo method, FieldInfo lazyInitializerField, Type parentType)
at NHibernate.Proxy.NHibernateProxyBuilder.CreateProxiedMethod(TypeBuilder typeBuilder, MethodInfo method, FieldInfo lazyInitializerField, Type parentType)
at NHibernate.Proxy.NHibernateProxyBuilder.CreateProxyType(Type baseType, IReadOnlyCollection`1 baseInterfaces)
at NHibernate.Proxy.StaticProxyFactory.CreateProxyActivator(ProxyCacheEntry pke)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at NHibernate.Proxy.StaticProxyFactory.GetProxy(Object id, ISessionImplementor session)

异常根源在于NHibernate代理生成逻辑中,ProxyBuilderHelper.GenerateMethodSignature方法使用SingleOrDefault获取泛型参数的类约束时,发现存在多个符合条件的类约束:

var typeConstraints = typeArg.GetGenericParameterConstraints()
    .ToArray(x => ResolveTypeConstraint(method, x));

var baseTypeConstraint = typeConstraints.SingleOrDefault(x => x.IsClass);

调用代码的泛型约束仅指定了基类:

public TEntity GetProxy<TEntity>(Guid id) where TEntity : Entity
{
    ...
    return Session.Load<TEntity>(id);
}

解决方案

  1. 检查实体类及继承链的泛型约束
    排查TEntity对应的实体类、其继承的基类、实现的接口中,是否存在某个泛型方法/接口的泛型参数带有多个隐式类约束(比如基类继承了另一类,同时接口又对泛型参数添加了类约束,导致传递后出现多个类约束的情况)。

  2. 切换代理生成器
    替换默认的静态代理生成器为Castle动态代理:

    • 安装NHibernate.Bytecode.Castle NuGet包
    • 在NHibernate配置中添加:
      configuration.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, 
          typeof(NHibernate.Bytecode.Castle.CastleProxyFactoryFactory).AssemblyQualifiedName);
      
  3. 升级NHibernate版本
    该问题可能是5.5版本的已知bug,尝试升级到5.5.x的最新补丁版本,或直接升级到5.6及以上稳定版本,看是否已修复该代理生成逻辑的问题。

  4. 清理实体类的冗余泛型约束
    检查实体类中的泛型方法,确保没有出现多个类约束的情况(C#语法不允许显式定义,但可能存在旧代码的特殊写法或反射生成的异常类型),如有则调整为单一类约束。

内容的提问来源于stack exchange,提问作者Mud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:26:19