如何使用标识列为NHibernate实体实现GetHashCode?

时间:2013-08-22 19:03:09

标签: c# sql-server nhibernate

我得出的结论是,对于具有标识列的NHibernate实体,无法正确实现GetHashCode()。我找到的唯一可行的解​​决方案是返回常量。请参阅下面的说明。

显然,这很可怕:所有字典搜索都有效地变为线性。我错了吗?我错过了一种解决方法吗?

解释

假设我们有一个Order实体引用一个或多个这样的Product实体:

class Product
{
    public virtual int Id { get; set; } // auto; assigned by the database upon insertion
    public virtual string Name { get; set; }
    public virtual Order Order { get; set; } // foreign key into the Orders table
}

“Id”是SQL Server术语中所谓的IDENTITY列:插入记录时由数据库自动生成的整数键。

现在,我有哪些选项来实施Product.GetHashCode()?我可以基于

  • Id
  • Name
  • 产品对象的标识(默认行为)

这些想法中的每一个都不起作用。如果我将我的哈希代码基于Id,它将在对象插入数据库时​​更改。以下实验证明,至少在NHibernate.SetForNet4:

存在的情况下会破坏
/* add product to order */

var product = new Product { Name = "Sushi" }; // Id is zero
order.Products.Add(product); // GetHashCode() is calculated based on Id of zero
session.SaveOrUpdate(order); 

// product.Id is now changed to an automatically generated value from DB
// product.GetHashCode() value changes accordingly
// order.Products collection does not like it; it assumes GetHashCode() does not change

bool isAdded = order.Products.Contains(product); 

// isAdded is false; 
// the collection is looking up the product by its new hash code and not finding it

基于GetHashCode()对象标识(即将Product保留为默认实现)也不能正常工作,之前已在StackOverflow中进行了介绍。如果GetHashCode()可变,那么Name基于Name显然不是一个好主意。

那么,还剩下什么?唯一对我有用的是

class Product
{
    ...
    override public GetHashCode() { return 42; }
}

感谢您阅读这篇长篇大论。 您对如何改善它有什么想法吗?

PS。请记住,这是一个NHibernate问题,而不是收集问题。集合类型和操作顺序不是任意的。它们与NHibernate的工作方式紧密相关。例如,我不能简单地使Order.Products像IList那样。它将具有重要意义,例如需要索引/订单列等。

1 个答案:

答案 0 :(得分:2)

我会在Id上建立哈希码(显然是相等的),这是正确的做法。您的问题源于您在对象位于Dictionary中时修改Id的事实。对象在哈希码和相等性方面应该是不可变的,而它们在字典或哈希集中。

您有两种选择 -

  1. 在将数据存储到数据库
  2. 之前,不要填充字典或散列集
  3. 在将对象保存到数据库之前,请将其从字典中删除。将其保存到数据库,然后再将其添加到字典中。
  4. <强>更新

    使用其他映射也可以解决问题

    1. 您可以使用行李映射 - 它将映射到IList,并且应该可以正常使用。无需使用HashSets或Dictionaries。
    2. 如果数据库架构在您的控制之下,您可能希望考虑添加索引列并使关系有序。这将再次映射到IList,但将具有List映射。
    3. 性能存在差异,具体取决于您的映射和方案(请参阅http://nhibernate.info/doc/nh/en/#performance-collections-mostefficientupdate