NHibernate second level cache for subclass only - nhibernate

I am using many classes per table mapping(subclasses with discriminator).
Is there a way to turn on second level caching for specific subclass only ?
NHibernate version is 3.1.0
If I put the tag <cache usage="read-only"/> right after the subclass tag, I get error at runtime(tells that cache is invalid child element for element subclass).
<class name="MyDomain.ParentClass, MyDomain" table="MyDomainClass">
<subclass name="MyDomain.SubClass, MyDomain" discriminator-value="SubClass">
</subclass>
</class>

NHibernate documentation (ch. 25.1) says:
Add <cache usage="read-write|nonstrict-read-write|read-only"/> (just after <class>) in the mapping of the entities you want to cache. It also works for collections (bag, list, map, set, ...).
So, sadly, no subclass.

Related

Is there a way for NHibernate to inform query cache from views to be invalidated?

I made a view out of joined tables, and I wanted its 2nd level query cache to be invalidated when the view's base table(s) are updated(within ORM context). The view is mapped like a table on NHibernate
Is this possible on NHibernate? How this is done on xml mapping? Fluent mapping will do too
Believe or not, even this is possible with NHibernate. If you'd have for example class mapped like this:
<class name="Contact" table="[dbo].[Contact]" lazy="true" >
<cache usage="read-write" region="ShortTerm"/>
And there is a view on top of the table [dbo].[Contact] which is mapped to another class:
<class name="ViewContact" table="[dbo].[ViewContact]" lazy="true" >
<cache usage="read-write" region="ShortTerm"/>
<!-- at this moment the View and table are treated differently -->
Then the magic setting goes directly under the <cache> and and is called <synchronize>
<class name="ViewContact" table="[dbo].[ViewContact]" lazy="true" >
<cache usage="read-write" region="ShortTerm"/>
<synchronize table="[dbo].[Contact]"/>
<!-- now both caches are synchornized -->
And now, any changes to mapped class Contact will also trigger the cache cleaning of the ViewContact class mapped to the view

NHibernate.Engine.ForeignKeys - Unable to determine if entity is transient or detached

I have this Instrument entity:
<class name="Instrument" table="Instruments" mutable="false">
<id name="ID" column="INSTRUMENT_ID" unsaved-value="0">
<generator class="assigned" />
</id>
<property name="....." />
<property name="....." />
</class>
This entity is used in many-to-one relationship in other entity (InstrumentSelection). This is many-to-one mapping info:
<many-to-one name="Instrument" access="field.camelcase" column="Instrument_ID" update="false" class="Instrument" not-null="true" fetch="join" lazy="false" />
The issue I've it that when I save InstrumentSelection entity with Save:
Transact(() => session.Save(entity));
I get error in logs:
2012-12-20 14:09:54,607 WARN 12 NHibernate.Engine.ForeignKeys - Unable
to determine if Instrument with assigned
identifier 11457 is transient or detached; querying the database. Use
explicit Save() or Update() in session to prevent this.
A few facts about Instrument entity:
It's just a reference entity
It's immutable entity
It can not be added / inserted via application. I get rows in database from external feed.
Question (version 1): A my question is: is there a way to instruct NHibernate to always consider Instrument entity as detached? I mean - if an instance of Instrument exists in application it means that it's present in database. So there is no too much sense in quering the database.
EDIT 1: Because Question (version 1) was not answered yet, let me change it slightly:
Question (version 2): What could be the behaviour that NHibernate is still trying to work out whether entity is detached/transient? I think I have my mapping configured correctly (unsaved-value, generator).
The problem is that when you save the InstrumentSelection, NHibernate is cascading the operation to save the child Instruments. My first suggestion is to set cascade to none on the InstrumentSelect side of the relationship.
My second suggestion is to use an interceptor as shown in this answer.

Mapping inherited class with nhibernate hbm

I Have 2 classes of the same table.
one class, "Entity", contains properties x,y,z from table ENTITY
and the derived class, "ExtendedEntity" contains some more properties (collections - relations to other tables).
I want to map both of them but i couldn't find a way to map subclasses without using discriminator (I dont need one, sometimes i want to select the Entity object and sometimes the ExtendedEntity).
does anyone has any idea?
(I tried to map the ExtendedEntity by copying the Entity mapping and adding the new properties, but now when i want to get the Entity object it brings me ExtendedEntity).
Thanks!
Taking into account the first sentence of your question:
I Have 2 classes of the same table.
It means that there is only one table ("ENTITY"). If this is true, there do not have to be, and even should not be any inheritance, if no discriminator exists. If both entities will be related to all rows, then (instead of inheritance) we need laziness. And only one Entity profiting from the native NHibernate behavior: having lazy properties. And even more, to optimize some queries - the Projections could be used.
But again, my suggestion could be correct only if I do understand your scenario correctly: the two entities were introduced only to reduce workload; but both target all rows in one table.
The mapping for the only class
<class name="Entity" table="ENTITY" lazy="true">
<id name="ID" column="Entityd">
<generator class="native"></generator>
</id>
<!-- standard default always loaded properties -->
<property name="Code" />
<property name="Name" />
<!-- only if accessed, lazily loaded properties -->
<many-to-one lazy="proxy" name="Currency" column="CurrencyId" cascade="none" />
<property lazy="true" name="Image" column="ImageBinary" />
...
Having this mapping we can get first 5 Entities
var list = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.List<Entity>();
And SQL statement generated will be:
SELECT TOP 5 this_.EntityId as EntityId3_1_
, this_.Code as Code3_1_
, this_.Name as Name3_1_
FROM ENTITY this_
And we can even reduce it with projections
var propertyList = NHibernate.Criterion.Projections.ProjectionList();
// projection properties
propertyList.Add(NHibernate.Criterion.Projections.Property("ID"));
propertyList.Add(NHibernate.Criterion.Projections.Property("Code"));
var projected = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.SetProjection(propertyList)
.SetResultTransformer(new NHibernate.Transform
.AliasToBeanResultTransformer(typeof(Entity)))
.List<Entity>();
In this case is the SQL Select even smaller. If the ID and Code would be enough..
SELECT TOP 5 this_.Code as y0_
, this_.EntityId as y1_
FROM ENTITY this_
So, in case I read your question correctly, in your scenario solution would not be in inheritance but in NHibernate native laziness
NOTE: there could be ExtendedEntity derived from Entity even in this scenario. But not for inheritance via NHibernate mapping but for the Projections Transformation. Some properties from many-to-one properties could be projected this way...

nHibernate mapping generic IDictionary

I've asked this elsewhere and not got any sensible reply
I'm trying to map an IDictionary. I have this mapping:
<class name="MyProject.Item, MyProject" table="Item">
<...>
<map name="Properties" access="property" table="ItemProperties" lazy="false">
<key column="ItemID" />
<index column="Idx" type="int" />
<element column="Value" type="System.Boolean, mscorlib"/>
</map>
I can persist data, but when the data is retrieved I get an nHibernate exception:
{"The value "0" is not of type "Project.PropertyType" and cannot be used in this generic collection. Parameter name: key"}
So it can't map to the enum, but why ? if I have a regular property that uses an enum, it works fine.
Is what I'm trying to do even possible ? I can't find much info on doing this.
Your mapping shows the key as an integer, not as an enum. To map the enum properly, use type="MyProject.Project.PropertyType, MyProject".
However, normally for an enum the best approach is to leave the type information out of the mapping file altogether and let NHib pick it up through reflection. My reading of the NHib source implies that if you are mapping into a generic IDictionary<K,V> then NHib should pick up the exact type of your key via reflection. IOW you still should be able to leave out the type attribute.

How can I map a list of strings to my entity using NHibernate?

I've got two tables in my database: Articles and Tags
The Tags tables consist of ArticleID (foreign key) and a Tag (varchar).
Now I need to map an articles tags into a readonly collection on Article entity, either using IList Tags or ReadOnlyCollection Tags.
I've consulted the NHibernate reference material, but I can't seem to figure when to use Set, Bag and the other Nhibernate collections. I've seen examples using the ISet collection, but I really don't like to tie my entity classes to a NHibernate type.
How can I do the mapping in NHibernate?
edit: I ended up using a <bag> instead, as it doesn't require an index:
<bag name="Tags" table="Tag" access="nosetter.camelcase" lazy="false">
<key column="ArticleId" />
<element column="Tag" type="System.String" />
</bag>
The type of collection to use in your mapping depends on how you want to represent the collection in code. The settings map like so:
The <list> maps directly to an
IList.
The <map> maps directly to an IDictionary.
The <bag> maps to an IList. A does not completely comply
with the IList interface because the
Add() method is not guaranteed to
return the correct index. An object
can be added to a <bag> without
initializing the IList. Make sure to
either hide the IList from the
consumers of your API or make it
well documented.
The <set> maps to an Iesi.Collections.ISet. That
interface is part of the
Iesi.Collections assembly
distributed with NHibernate.
so if you want an IList to be returned, then you would use the <list> mapping. In your case, I'd probably map using the <list> mapping.