I use NHibernate's second level cache on an object whose primary key is a string column. The database is not case sensitive, however, when I retrieve an object using the same ID but with a different body, then NHibernate treats the object as another object in the cache. For example, I have a settings table with the Name column as the primary key. If I try to restore the object using session.Get<Setting>("TestMode") , Get<Setting>("testmode") or Get<Setting>("testmode") , which will go to the database 3 times and put 3 separate object in the cache of the second level. If I then changed something to my installation object via NHibernate, it will update the cached object, which actually corresponds to the casing on the entity, since it is stored in the database (in this case, the one called TestMode). The problem is that the rest of the objects will still be in the cache, but will be obsolete.
I understand why NHibernate treated identifiers as case sensitive by default, but there seems to be no way to set case sensitivity at the entity level or configuration level as far as I can find. Can this be done, and if so, how?
If this helps, I use Fluent NHibernate. The column "Identifier" is indicated as such:
Id(x => x.Name).GeneratedBy.Assigned().Column("Name");
UPDATE The following are the implementations of Equals () and GetHashCode () from the Setting object.
public override bool Equals(object obj) { if (obj == null) return false; if (obj is Setting) { if (object.ReferenceEquals(this, obj)) return true; if (this.Name.Equals(((Setting)obj).Name, StringComparison.OrdinalIgnoreCase))
UPDATE 2 I profiled the NHibernate Profiler and made retries for "TestMode", "testmode", "TestMode", "Testmode", "TESTMODE" (in that order), it shows only cache hit for the second "TestMode". It shows "Setting the load on the cache of the 2nd level (TestMode / * id * /)", all the others show SELECT ... FROM Setting setting0_ WHERE setting0_.Name = "testmode" (in any case, which requested a call). When I click on the link “Look at 1 row (s) obtained as a result of this statement”, it shows me a row with the “Name” column having the correct “TestMode” body, so it explicitly retrieves the object with the right shell for the column itself, but it seems that it definitely associates the entity with the identifier with which the Get () function was called. It does not look like it should be normal behavior, but I could not find any information about the specifics of the operation of the 2nd level cache, as well as just how to use it in the NHibernate cookbook.
Although I doubt this should change, I use HashtableCacheProvider for all of these tests. (for production we will use a paid caching provider)