我正在从非常旧的 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 typeArgs = method.GetGenericArguments();
if (typeArgs.Length > 0)
{
var typeNames = GenerateTypeNames(typeArgs.Length);
var typeArgBuilders = methodBuilder.DefineGenericParameters(typeNames);
for (var index = 0; index < typeArgs.Length; index++)
{
// Copy generic parameter attributes (Covariant, Contravariant, ReferenceTypeConstraint,
// NotNullableValueTypeConstraint, DefaultConstructorConstraint).
var typeArgBuilder = typeArgBuilders[index];
var typeArg = typeArgs[index];
typeArgBuilder.SetGenericParameterAttributes(typeArg.GenericParameterAttributes);
// Copy generic parameter constraints (class and interfaces).
var typeConstraints = typeArg.GetGenericParameterConstraints()
.ToArray(x => ResolveTypeConstraint(method, x));
var baseTypeConstraint = typeConstraints.SingleOrDefault(x => x.IsClass);
typeArgBuilder.SetBaseTypeConstraint(baseTypeConstraint);
var interfaceTypeConstraints = typeConstraints.Where(x => !x.IsClass).ToArray();
typeArgBuilder.SetInterfaceConstraints(interfaceTypeConstraints);
}
}
它获取泛型类型参数的一组约束,然后尝试找到“IsClass == true”的约束,显然有多个约束。我不知道这意味着什么或如何解决它。
这是调用方法。类型约束是针对类的:
public TEntity GetProxy<TEntity>(Guid id) where TEntity : Entity
{
...
return Session.Load<TEntity>(id);
}
我的实体类的方法之一具有具有多个目标类的子类类型约束,例如
protected virtual SomeMethod<T>(T arg): where T: Foo, Bar
。
不是
:
之后的逗号分隔列表。 NHibernate 对此感到窒息,因为代理生成代码中的这段代码(ProxyBuilderHelper.cs 中的 GenerateMethodSignature()):
var typeConstraints = typeArg.GetGenericParameterConstraints()
Select(x => ResolveTypeConstraint(method, x));
var baseTypeConstraint = typeConstraints.SingleOrDefault(x => x.IsClass);
IsClass == true 存在多个类型约束,因此 SingleOrDefault 会抛出异常。
在这种情况下,我能够删除第二种类型的约束,并且问题得到解决。