GetHashCode()
ID 列を持つ NHibernate エンティティを適切に実装することは不可能であるという結論に達しました。私が見つけた唯一の実用的な解決策は、定数を返すことです。説明については、以下を参照してください。
これは明らかにひどいことです。すべての辞書検索は実質的に直線的になります。私が間違っている?私が見逃した回避策はありますか?
説明
次のような 1 つ以上の Product エンティティを参照する Order エンティティがあるとします。
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 (デフォルトの動作)
これらのアイデアはどれも機能しません。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()
オブジェクト ID に基づく (つまり、デフォルトの実装のままにProduct
する) こともうまく機能しません。これは以前に StackOverflow で取り上げられました。変更可能な場合、に基づくGetHashCode()
ことName
は明らかに良い考えではありませんName
。
それで、何が残っていますか?私のために働いた唯一のことは
class Product
{
...
override public GetHashCode() { return 42; }
}
この長い質問を読んでくれてありがとう。 それをより良くする方法について何かアイデアはありますか?
PS。これは NHibernate に関する質問であり、コレクションに関する質問ではないことに注意してください。コレクションの型と操作の順序は任意ではありません。それらは、NHibernate の動作方法に関連付けられています。たとえば、単純に Order.Products を IList のようなものにすることはできません。インデックス/順序列が必要になるなど、重要な意味があります。