gpt4 book ai didi

nhibernate - NHibernate升级使用具有类型约束的方法破坏了EntityBase

转载 作者:行者123 更新时间:2023-12-04 01:49:20 25 4
gpt4 key购买 nike

对于长篇文章,请提前道歉。我希望有人能提供帮助。

我被要求在ASP.NET应用程序中升级NHibernate(从2.1.2.4000到3.3.1.4000)和Fluent NHibernate(从1.1.0.685到1.3.0.0)。我是NHibernate的新手,但花了数周的时间进行研究,因此我有所了解。

例如,我知道较新版本的NHibernate具有内置的代理生成器,因此我删除了对旧NHibnernate.ByteCode.Castle.dll的任何引用,该引用是我们以前使用的代理生成器,因此摆脱了引用从nhibernate.config到该文件,目的是使用内置代理。

我已经成功地解决了许多问题,但遇到了我遇到的问题,在网络上发现的任何东西似乎都与之完全不符。这是令人惊讶的,因为我本以为执行此升级的任何人都会遇到此问题,但是也许这只是我们编写Entity Base类的方式。

有两种Visual Studio解决方案,一种是“框架”解决方案,其中包含EntityBase类,另一种是主要应用程序解决方案,其使用框架解决方案中的DLL。

在EntityBase类中,有两种方法返回“真实”对象而不是代理,这与此处描述的“ As”方法非常相似:http://sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html

据我了解,这些方法实际上返回的是由NHibernate代理对象包装的“真实”(域)对象。在我的情况下,有问题的方法称为“ CastTo”和“ AsOfType”。这些方法的类型约束似乎导致了我的问题。

这是我的EntityBase类的相关代码:

/// <summary>
/// Represents the base class for a domain entity.
/// </summary>
/// <typeparam name="TIdentity">The type of the identity.</typeparam>
/// <remarks>
/// This class implements all the interfaces that all domain entities must have.
/// </remarks>
[Serializable]
public abstract class EntityBase<TIdentity> : IAuditable, IEntity<TIdentity>, IPersistent
{
/// <summary>
/// Casts to.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual T CastTo<T>() where T : EntityBase<TIdentity>
{
return (T)this;
}

/// <summary>
/// Casts this entity to the type passed in.
/// This is required when trying to cast from a proxy.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual T AsOfType<T>() where T : EntityBase<TIdentity>
{
return this as T;
}


因此,当我在主应用程序解决方案中运行单元测试时,出现如下错误:

创建代理实例失败---> System.TypeLoadException:程序集'LocationProxyAssembly,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'中类型'LocationProxy'的方法'AsOfType'试图隐式覆盖类型较弱的方法参数约束。

因此,似乎正在创建NHibernate代理的Reflection.Emit代码抱怨AsOfType和CastTo方法的类型约束。

因此,我以为我会放宽那些约束,而不是在类型约束中不使用泛型,而是尝试仅使用“ Entity”作为约束(从EntityBase派生的类)。因此,我尝试了以下操作(是的,我知道这两个方法本质上是在做同一件事,但我只是想保留EntityBase类的接口,以避免破坏对这些方法的所有调用):

[Serializable]
public abstract class EntityBase<TIdentity> : IAuditable, IEntity<TIdentity>, IPersistent
{
/// <summary>
/// Casts to.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual T CastTo<T>() where T : Entity
{
if (!typeof(T).IsAssignableFrom(GetType()))
{
throw new InvalidCastException();
}

return this as T;
}

/// <summary>
/// Casts this entity to the type passed in.
/// This is required when trying to cast from a proxy.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public virtual T AsOfType<T>() where T : Entity
{
return this as T;
}


因此,现在测试以另一种方式失败了。我有一个看起来像这样的单元测试:

    /// <summary>
/// Tests the type of the get real.
/// </summary>
[TestMethod, TestCategory("Integration")]
public void TestEntityProxyCastToMethod()
{
using (var unitOfWork = UnitOfWork.Begin(Database.MainSolution.Name()))
{
var person = unitOfWork.GetProxy<Person>(new Guid("E196BC94-DFBA-4D6C-B504-03E00F5CA914"));

Assert.IsTrue(person.IsOfType<Employee>());

var employee = person.AsOfType<Employee>();

Assert.IsNotNull(employee);
}
}


现在运行单元测试时抛出的异常是:

测试方法MainSolution.Data.Tests.EntityProxyTests.TestEntityProxyCast引发异常:
System.InvalidOperationException:无法对包含ContainsGenericParameters为true的类型或方法执行后期绑定操作。

因此,这似乎仍然是一些Reflection.Emit错误,这是在NHibernate尝试生成代理时发生的。显然,NHibernate现在生成其代理的方式与我们编码EntityBase类的方式不兼容。当我们使用NHibernate.ByteCode.Castle.dll生成代理时,它可以正常工作,但显然对这些方法的类型约束不满意。

现在,我看到了类似这样的帖子( Nhibernate: Get real entity class instead of proxied class),这些帖子建议我们只应“取消代理”类即可获得基础的“真实”对象。但这意味着(可能)更改这些方法的签名,中断对“ CastTo”和“ AsOfType”方法等的所有调用。据我了解,我必须获得一个UnitOfWork,从中获取当前会话,然后执行“ Unproxy”操作以获取基础对象,而对于当前代码,我们要做的基本上就是返回“ this as T”,并且它将起作用。我以为也许可以在调用代码中获取当前会话,然后将其传递到EntityBase上的某个方法中,但这看起来很丑陋,并且做起来似乎应该更简单的事情会产生很多开销。

因此,问题是:a)我在做什么错,b)在3.3的情况下我如何正确地做到这一点。版本的NHibernate,以及c)有没有办法在我的EntityBase类上保留“ CastTo”和“ AsOfType”方法的现有签名,同时仍然让NHibernate正确生成代理,而无需抱怨这些方法的类型约束?

任何帮助表示赞赏,非常感谢。

最佳答案

有JIRA问题:


https://nhibernate.jira.com/browse/NH-2726
https://nhibernate.jira.com/browse/NH-2819


甚至有一个拉取请求,可惜它尚未被拉出:


https://github.com/nhibernate/nhibernate-core/pull/129


编辑:拉请求被拉,所以此特定问题已修复。但是还有另一个问题也会影响.NET 2.0运行时:https://nhibernate.jira.com/browse/NH-3244

但是,仅使用“实体”作为约束的代码现在应该可以工作。

关于nhibernate - NHibernate升级使用具有类型约束的方法破坏了EntityBase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11844763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com