nhibernate table per subclass strategy problem when getting objects - nhibernate

I am working on an ASP.NET Web application that uses NHibernate and I have noticed something funny.
So I have an object Document which I would make into an abstract class and 2 concrete implementations Document1 and Document2.
I tried to write the mappings for them applying the table-per-subclass strategy as described in the documentation(link text):
<class name="Document" abstract="true">
<id name="Id">
<generator class="identity"/>
</id>
...
<class>
<joined-subclass
name="Document1"
extends="Document" >
<key column="ParentId"/>
...
</joined-subclass>
<joined-subclass
name="Document2"
extends="Document" >
<key column="ParentId"/>
...
</joined-subclass>
Now this is how I obtain objects from the session in my application:
public TEntity GetById<TEntity>(object id) {
return Session.Get<TEntity>(id);
}
Now my problem is that when I do:
GetById<Document>(1)
for example, I don't get a Document object I get an object of type Document1 or Document2 depending on which type that object is.
I tryed using the table-per-subclass with discriminators strategy as mentioned in the documentation(link above) and I set join=select and lazy=false on the abstract object to get it to return an object of type Document but nothing worked.
The code works but it doesn't seem right. I have a left join where I could not use one.
Isn't there a way to just get the abstract object or does nhibernate actually instantiate the objects it returns which would make this impossible? Is it possible?
I have the feeling that I am getting more info than I need.

You'll never get the abstract class because the whole point of an abstract class is that you can't instantiate one. Besides your code will return only the Document facade to the rest of your code anyway. So I'm not sure what the problem really is.

It is not possible to retrieve an instance of Document1 or Document2 that only populates the properties that are defined in the abstract class. In .NET, you are always working with an instance of a concrete class even if the type is declared as an interface or abstract class.

Related

Handle cases where Nhibernate subclass does not exist

I have a scenario where I am using nhibernate to map records from one table to several different derived classes based on a discriminator.
public class BaseClass { }
public class DerivedClass0 : BaseClass { }
public class DerivedClass1 : BaseClass { }
public class DerivedClass2 : BaseClass { }
I then use nhibernate's DiscriminateSubClassesOnColumn() method and alter the configuration to include
<subclass name="DerivedClass0" extends="BaseClass" discriminator-value="discriminator0" />
<subclass name="DerivedClass1" extends="BaseClass" discriminator-value="discriminator1" />
<subclass name="DerivedClass2" extends="BaseClass" discriminator-value="discriminator2" />
so that when mapped, these classes are cast to their derived classes and not BaseClass.
However, there are some records in my database which have a discriminator which does not have a corresponding subclass. In these cases, nHibernate throws an error:
"Object with id: 'xxx' was not of the specified subclass..."
Is there some way I can handle this, so that any records which do not have a corresponding subclass are cast to BaseClass rather than an error being thrown?
I have simplified the above as much as possible, however it is worth noting that the XML is edited dynamically which is why I am referencing fluent nhibernate [DiscriminateSubClassesOnColumn()] and XML at the same time.
The following things (which would help) are not an option:
I cannot correct the data to remove records which are invalid
I cannot create subclasses for those records which do not have one
I need to handle cases where nHibernate tries to map on a discriminator and finds that one does not exist.
The solution is to use the "AlwaysSelectWithValue()" method in the Fluent NHibernate mapping.
DiscriminateSubClassesOnColumn("discriminator").AlwaysSelectWithValue();
This forces NHIbernate to only fetch results from the database which have a corresponding subclass.

NHibernate Guid generator if new

I'd like NHibernate to generate guids for entities only if they are not set manually by the user or application. Basically, when saving objects with new Guid() (all zeros), NHibernate should generate one. When saving an object that has a non-zero Guid, it should use that instead.
Is my only option to write my own generator?
edit Folks, I'm aware of 'assigned'. I should have specified I was aware of it. Since it doesn't do what I want it to do, it's not the option I'm looking for. Writing my own generator is an option that works, but I'd like something else. I'm suspecting there is nothing else.
The problem here is that NH needs to know if the object is new or if it already exists. It does this usually by setting the ID.
If you wrote your own generator, it doesn't solve the problem, because it is only called if the object is new.
You could use the assigned generator.
You could use a version column to indicate if the object is new. I never tried it this way, but it should work. NOT having any indication for NH if the object is new causes quite some troubles. Believe me.
You could also have a integer as primary key and the GUID as regular unique field.
I whould generate the id in the class' constructor
class Entity
{
Guid id;
Entity(Guid id = Guid.Empty)
{
if (id == Guid.Empty) this.id = Guid.NewGuid();
else this.id = id;
}
}
Have you tried setting the unsaved-value attribute?
<id name="Id" column="Id" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
<generator class="guid.comb" />
</id>
edit now I understand your question fully another option instead of rolling out your own generator is to use
<generator class="assigned" />
However you cannot use SaveOrUpdate(). Instead you have to explicitly specify to NHibernate if the object should be saved or updated by calling either the Save() or Update() method of the ISession. Also you will always need to set the GUID manually on all your NEW entities. Its an option.

How to map an NHibernate entity property using both a formula and a column specification

I'm trying to map an entity property in such way that it writes its value to a database column but retrieves its value using a formula.
To focus on the actual issue, I have simplified the example. In reality the formula is a bit more complex and is using an NHibernate filter.
<many-to-one cascade="all" class="Thing" lazy="false" name="MyThing"
formula="(SELECT Things.Value FROM Things WHERE Things.Id = MyThingId)">
<column name="MyThingId" />
</many-to-one>
The formula is ignored however, unless I remove the <column name="MyThingId" /> line.
How would I fix this mapping in order to have NHibernate use the formula?
I don't think it's possible to do exactly what you are trying.
Why not split the property in two? One readonly for the formula and the other read/write with a direct column mapping...
If you still want a single access point, you can map a third ignored propery that implements it's get and set accessors with the two first properties.

NHibernate: How to disable virtual for class properties?

how exactly I can use public methods (non-virtual) with NHibernate?
I have this code:
public string crewNumber
{
get
{
return this.crewNumberField;
}
set
{
this.crewNumberField = value;
}
}
Note all my classes, properties, methods and interfaces are auto-generated and I do not want to change them manually.
Above code is producing this error:
The following types may not be used as
proxies: ... method get_crewNumber
should be 'public/protected virtual'
I see that it shold be possible to use simple public only properties here:
In our example above, we've made the
properties and the constructor public
- but that's not a requirement for NHibernate - it can use public,
protected, internal, or even private
properties to persist your data.
How do I turn off this virtual by default?
It's driving me crazy. I am really tempted here to drag one data adapter in visual studio and to end this ridiculous situation once and for all ;-)
Thanks
Specify that dynamic proxies should not be used for that class, by specifying lazy=false on the class-mapping.
Like this:
<class name="MyClass" table="MyTable" lazy="false">
</class>
This means offcourse that you cannot use dynamic proxies with NHibernate.
To be more clear:
- when you retrieve an instance of your class, which is able to use dynamic proxies, you'll recieve an 'empty instance'. That is, NHibernate will not fetch the data from the DB yet. You'll get an object who'se Id will be populated, but the other properties are not. Only when you access a property, then NHibernate will load the data from the DB. That's the reason why the properties need to be virtual, because NHibernate will create a subclass of your class internally, and override the properties so that it can achieve this behaviour.
I always specify 'lazy=false' on my class-mapping, since I don't want to have virtual properties for a reason that is infrastructure-related, instead of 'domain-related'.
(Note that this has nothing to do with lazy loading of associations; it is still possible to have them lazy loaded when you do not use dynamic proxies).
Put lazy="false" at the class mapping:
<class name="MyClass" table="MY_TABLE" lazy="false">

nhibernate lazy load options

What is the difference between lazy="true" and lazy="proxy" in nhibernate?
I suspect another way of thinking about it would be this.
class Foo
{
public virtual Bar SingleBar { get; set; }
public virtual ICollection<Bar> MultiBar { get; set; }
}
lazy="proxy" applies to single objects (ie foo.SingleBar)
lazy="true" applies to collections of objects (ie foo.MultiBar)
(You can't set lazy="proxy" to a collection, nor can you set lazy="true" to a single reference. Either will cause NH to throw a XmlSchemaException which is a little cryptic to beginners.)
Operationally they do the same abstract thing: when and only when the property is accessed does NHibernate hit the database and populate the property.
There is however a slight difference in the implementation due what is needed to fetch the objects (in the single case, the reference's id (Bar) was loaded with the parent entity (Foo). In the collection case, the ids are unknown and must be found in another table)
lazy="proxy" means that NHibernate will lazily initialize instances of your class;
When NHibernate retrieves an instance of your class from the database, it will - in this case - not return a 'real' instance of your class, but it will rather give you a proxy. That is, it will return an object that is of another type, more specifically, an object that is a subclass of your class (generated by NHibernate through IL generation).
The object that you will be given, is a proxy, and the only populated property, is the Id property. As soon as you call another property on the instance, NHibernate will initialize the proxy, and retrieve all the other properties / collections (except those that are lazy loaded) from the database.
Lazy="true" is used on another level. Whereas lazy="proxy" is used on the class-level, lazy="true" is used on the collection level. It means that the collection should be lazy loaded.
The documentation reference says that the value of the proxy attribute is in:
lazy="proxy|no-proxy|false"
lazy (optional - defaults to proxy): By default, single point associations are proxied.
lazy="no-proxy" specifies that the property should be fetched lazily when the instance variable is first accessed (requires build-time bytecode instrumentation).
lazy="false" specifies that the association will always be eagerly fetched.
By default, Hibernate3 uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#performance-fetching-lazy