gpt4 book ai didi

Nhibernate iesicollection 包含返回 false

转载 作者:行者123 更新时间:2023-12-04 06:16:24 25 4
gpt4 key购买 nike

Nhibernate 强制您使用 Iesi Set,而不是 net 4 ISet 接口(interface)。在以下代码片段中,我检查 iesi 集是否包含项目:

    public virtual void Remove(Substance substance)
{
var test = _substances.First() == substance;

if (!_substances.Contains(substance)) return;

_substances.Remove(substance);
substance.SubstanceGroup = null;
}

变量 _substances 引用了一个 HashedSet。我添加了测试变量只是为了检查代码作为临时措施。
我像这样重写了 Equals 方法:
    public override int GetHashCode()
{
return Equals(Id, default(TId)) ? base.GetHashCode() : Id.GetHashCode();
}

这会导致项目将 Id (Guid) 作为散列返回。
如果我 checkin 调试器,我会得到以下结果:
test
true
_substances.Contains(substance)
false
_substances.First().GetHashCode()
-2974953
substance.GetHashCode()
-2974953

怎么可能使用该集合的 contains 方法在集合中没有发现完全相同的对象?我什至可以在调试器中做到这一点:
_substances.Contains(_substances.First())
false

显然, _substances.Remove(substance) 也不起作用。经过一些额外的研究,我发现 NH 用它自己的 Persistent Generic 集替换了该集合。使用此套件时会出现问题。如果我从该集合中检索一个项目并在同一集合上调用包含,它总是返回 false。我已经覆盖了 GetHashCode 和 Equals,甚至将 return true 放在 Equals 方法中。

最佳答案

您的 Equals 和 GetHashCode 实现有问题,因为我向您保证 Iesi ISet 集合可以正常工作。它被 PersistentGenericSet 替换的原因是 ISet 只是一个接口(interface),集合必须替换为具体类型。如果没有更多代码,很难看出问题出在哪里,所以我在下面粘贴了一个更好的相等实现。我在您的问题中看到的一个问题是,在分配 Id 后哈希码会发生变化,我的版本通过缓存哈希码来处理这个问题。

public class Substance
{
private int? _cachedHashCode;

public Substance()
{
Id = Guid.Empty;
}

public Substance(Guid id)
{
Id = id;
}

public Guid Id { get; set; }

public bool IsTransient
{
get { return Id == Guid.Empty; }
}

public bool Equals(Substance other)
{
if (IsTransient ^ other.IsTransient)
{
return false;
}
if (IsTransient && other.IsTransient)
{
return ReferenceEquals(this, other);
}
return other.Id.Equals(Id);
}

public override bool Equals(object obj)
{
if (obj == null || obj.GetType() != GetType())
{
return false;
}
var other = (Substance)obj;
return Equals(other);
}

public override int GetHashCode()
{
if (!_cachedHashCode.HasValue)
{
_cachedHashCode = IsTransient ? base.GetHashCode() : Id.GetHashCode();
}
return _cachedHashCode.Value;
}
}

public class Mixture
{
public Mixture()
{
Substances = new HashedSet<Substance>();
}

public ISet<Substance> Substances { get; set; }
}

public class Tests
{
[Test]
public void set_contains_transient_substance()
{
var mixture = new Mixture();
var s1 = new Substance();
mixture.Substances.Add(s1);
Assert.IsTrue(mixture.Substances.Contains(s1));
}

[Test]
public void set_contains_persistent_substance()
{
var id = Guid.NewGuid();
var mixture = new Mixture();

var s1 = new Substance(id);
mixture.Substances.Add(s1);

var s2 = new Substance(id);
// these were created with the same id so hash code is not cached
// and id equality is used
Assert.IsTrue(mixture.Substances.Contains(s2));
}

[Test]
public void remove_substance()
{
var id = Guid.NewGuid();
var mixture = new Mixture();

var s1 = new Substance(id);
mixture.Substances.Add(s1);

var s2 = new Substance(id);
mixture.Substances.Remove(s2);
Assert.IsTrue(mixture.Substances.Count() == 0);
}

[Test]
public void hash_code_is_cached()
{
var s1 = new Substance(Guid.NewGuid());
var s2 = new Substance(Guid.NewGuid());

var mixture = new Mixture();
mixture.Substances.Add(s1);

Assert.IsFalse(mixture.Substances.Contains(s2));
// assign s1 id to s2, s2 hashcode is cached so they are not equal
s2.Id = s1.Id;
Assert.IsFalse(mixture.Substances.Contains(s2));
}

}

关于Nhibernate iesicollection 包含返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7190883/

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