Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/maven/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用NHibernate会话加载方法,是否有方法访问实体';没有初始化代理的id?_Nhibernate - Fatal编程技术网

使用NHibernate会话加载方法,是否有方法访问实体';没有初始化代理的id?

使用NHibernate会话加载方法,是否有方法访问实体';没有初始化代理的id?,nhibernate,Nhibernate,根据文档,session.Load(id) 返回一个对象,该对象是未初始化的代理,并且实际上没有命中数据库 这很好,因为我有一个场景,我想加载一个对象(我知道它存在于数据库中),然后(在同一个会话中)访问实体的id,通常只访问id,而不初始化代理。在我看来,如果我只访问代理的id,它就不必初始化。至少这是我希望的,但我似乎无法让它以那种方式工作 基本上,我正在尝试通过以下测试: [Test] public void Accessing_loaded_entity_id_should_not_in

根据文档,session.Load(id)

返回一个对象,该对象是未初始化的代理,并且实际上没有命中数据库

这很好,因为我有一个场景,我想加载一个对象(我知道它存在于数据库中),然后(在同一个会话中)访问实体的id,通常只访问id,而不初始化代理。在我看来,如果我只访问代理的id,它就不必初始化。至少这是我希望的,但我似乎无法让它以那种方式工作

基本上,我正在尝试通过以下测试:

[Test]
public void Accessing_loaded_entity_id_should_not_initialize_the_proxy()
{
    // Arrange
    var repo = new NHRepository<Order>();
    var order = new OrderBuilder().Build();

    repo.Save(order);
    repo.Flush();
    repo.Clear();

    // Act
    var fromDb = repo.Load(order.ID);

    // Assert
    Assert.AreEqual(order.ID, fromDb.ID);
    Assert.IsFalse(NHibernateUtil.IsInitialized(fromDb));
} 
[测试]
公共无效访问\u加载的\u实体\u id\u不应\u初始化\u代理()
{
//安排
var repo=new NHRepository();
var order=new OrderBuilder().Build();
回购保存(订单);
回购冲水();
回购清晰();
//表演
var fromDb=回购负载(订单ID);
//断言
arest.AreEqual(order.ID,fromDb.ID);
Assert.IsFalse(NHibernateUtil.IsInitialized(fromDb));
} 
此测试在此失败:

Assert.IsFalse(NHibernateUtil.IsInitialized(fromDb))

更新 以下是我的id的hbm映射:

<id name="id" access="field">
    <generator class="hilo">
        <param name="column">OrderNextHi</param>
        <param name="max_lo">100</param>
    </generator>
</id>

OrderNextHi
100
这是我的基本实体类型。我想问题可能就在这里,因为我很久以前就复制了这个,没有花太多心思。让我知道你的想法:

public abstract class SingleIdentityDomainEntity<T> where T : SingleIdentityDomainEntity<T>
{
    private readonly int id;
    private int? _oldHashCode;

    protected SingleIdentityDomainEntity()
    {
        this.id = 0;    
    }

    public virtual int ID
    {
        get { return this.id; }
    }

    public override bool Equals(object obj)
    {
        var other = obj as T;
        if (other == null)
            return false;

        // handle the case of comparing two NEW objects
        if (other.IsTransient() && this.IsTransient())
            return ReferenceEquals(other, this);

        return other.ID.Equals(this.ID);
    }

    /// <summary>
    /// Transient objects are not associated with an item already in storage.
    /// </summary>
    public virtual bool IsTransient()
    {
        return this.ID == 0;
    }

    /// <summary>
    /// Must be provided to properly compare two objects
    /// </summary>
    public override int GetHashCode()
    {
        // Once we have a hash code we'll never change it
        if (_oldHashCode.HasValue)
            return _oldHashCode.Value;

        // When this instance is transient, we use the base GetHashCode()
        // and remember it, so an instance can NEVER change its hash code.
        if (this.IsTransient())
        {
            _oldHashCode = base.GetHashCode();
            return _oldHashCode.Value;
        }

        return this.ID.GetHashCode();
    }
}
公共抽象类SingleIdentityDomainEntity,其中T:SingleIdentityDomainEntity
{
私有只读int-id;
私有整数?oldHashCode;
受保护的SingleIdentityDomainEntity()
{
此参数为0.id;
}
公共虚拟整数ID
{
获取{返回this.id;}
}
公共覆盖布尔等于(对象对象对象)
{
var other=作为T的obj;
如果(其他==null)
返回false;
//处理比较两个新对象的情况
if(other.IsTransient()&&this.IsTransient())
返回ReferenceEquals(其他,此);
返回其他.ID.Equals(this.ID);
}
/// 
///临时对象与已在存储器中的项不关联。
/// 
公共虚拟boolistransient()
{
返回this.ID==0;
}
/// 
///必须提供以正确比较两个对象
/// 
公共覆盖int GetHashCode()
{
//一旦我们有了散列码,我们就永远不会改变它
if(_oldHashCode.HasValue)
返回_oldHashCode.Value;
//当这个实例是暂时的时,我们使用基本的GetHashCode()
//记住它,这样实例就永远不会更改其哈希代码。
if(this.IsTransient())
{
_oldHashCode=base.GetHashCode();
返回_oldHashCode.Value;
}
返回此.ID.GetHashCode();
}
}

我不知道您对存储库的实现,但我认为您的问题在于:

repo.Clear();

线路。我猜它会清除您的会话(所有缓存值都会被逐出)。

您的断言是否实际强制从数据库加载。你能看到sql吗?@Mark,用var i=fromDb.ID替换这两个断言,我能用sql事件探查器验证select sql语句是否生成。你能在ID属性后面发布代码,以及ID属性与Order的映射吗?我不理解这里的问题。如果要初始化它,请使用Session.Get()@Darren。问题是,如果我只需要id,就不需要初始化它。这就是为什么我使用Load而不是Get,因为Get总是会命中数据库。这有意义吗?Clear()方法正在逐出所有缓存的值,这就是我调用它的原因。调用Load时,我不希望会话中存在订单obj。当我从回购中加载它时,我实际上需要代理。然后我希望,如果我只尝试从代理中获取id,代理将不会初始化,也不会得到db命中。显然,如果我在代理上调用另一个方法,我会期望db命中,但id应该已经加载到代理中,因为我将其用作加载方法的参数。这有意义吗?从nhibernate文档中可以看出:Hibernate从数据库中加载了多少数据,它将使用多少SQL选择?这取决于抓取策略。第19.1节“获取策略”对此进行了解释。这意味着您必须在映射中设置抓取策略。