nhibernate - hbm xml - complicated property ref attribute - nhibernate-mapping

I using nhibernate with hbm files (not fluent).
In the mapping hbm file,
I need to use the attribute property-ref but not in the simple way. I need to access to an inner proprty of an object.
I need to use it like this:
property-ref="object.property"
but it doesn't work...
Any suggestions?

Related

NHibernate setting access="field.camelcase-underscore" fails in version 3

I have a solution that was created with NHib 1.2 which we're upgrading to NHib 3.0.
Our hbm file has the following property:
<property name="ContentId" column="ContentId" access="field.camelcase-underscore" />
The class doesn't have a ContentId property. This was working fine in NHib 1.2 but now we're getting getting the following exception:
Could not compile the mapping document: XXXX.Core.Domain.Video.hbm.xml ---> NHibernate.MappingException: Problem trying to set property type by reflection ---> NHibernate.MappingException: class Core.Domain.Video, Core, Version=1.0.0.29283, Culture=neutral, PublicKeyToken=null not found while looking for property: ContentId ---> NHibernate.PropertyNotFoundException: Could not find the property 'ContentId', associated to the field '_contentId', in class 'Core.Domain.Video'.
Why would this stop working? Is it still supported in NHib 3?
We have many many properties like this that we might need to add.
NHibernate greatly improved its error messaging and diagnostics in NH2.X and again in NH3.X. You are telling NHibernate that you have a property and you want to map it via field access to a field named by _camelCase convention. You don't have a property named ContentId and NHibernate is letting you know that you lied to it. :)
Try updating your mapping to:
<property name="_contentId" column="ContentId" access="field" />
You will need to update any HQL or Criteria queries to use _contentId rather than ContentId. Another option would be to add a private ContentId property.
I'd like to provide information which helped me answer this question:
http://groups.google.com/group/nhusers/browse_thread/thread/e078734a221c3c0c/ec8b873b385d4426?lnk=gst&q=field+camelcase+underscore#ec8b873b385d4426
In this link Fabio explains the same problem you are having like this:
This mapping
<property name="PositiveValue" access="field.camelcase-underscore" />
mean: For my property named "PositiveValue" you (NH) have to access to
the field; to discover which is the associated field you (NH) have to
use the strategy "camelcase-underscore".
If there is no property you can't use the accessor with a specific
strategy.
Which struck me as a little odd because it meant adding dummy, unused properties, just to make the nhibernate3 compiler happy. The underlying functionality is the same.

FluentNHibernate CustomType("Binary") MappingException

I have an issue with mapping an entity with the latest FluentNHibernate build available on NuGet (package version: 1.1.1.694) and NHibernate 3.0 GA
What I am trying to reach is sql type: binary(64) with FluentNHibernate in a database-agnostic manner (I don't want to use CustomSqlType).
The default is varbinary(64) which I don't want. Lowercase "binary" leads to this as well.
My mapping code:
this.Map(x => x.PasswordHash)
.CustomType("Binary")
.Length(64)
.Not.Nullable();
Gives in NHibernate mapping XML file:
<property name="PasswordHash" type="Binary">
<column name="PasswordHash" length="64" not-null="true" />
</property>
Exception on generating schema:
Could not load type Binary.
System.TypeLoadException: Could not load type Binary. Possible cause: no assembly name specified.
at NHibernate.Util.ReflectHelper.TypeFromAssembly(AssemblyQualifiedTypeName name, Boolean throwOnError)
On the other hand CustomType("StringClob") works. Is there something I am missing ?
Is there a way to make FluentNHibernate .CustomType<> work with built-in NHibernate types ?
(Useful for AnsiChar, or other non-standard mapping between .NET type and database type) ?
I believe you have to change the sql-type, not the type (fluent syntax is probably .SqlType("binary") or something like that)

nHibernate 3, sql-query, IndexOutOfRangeException

In my nHibernate mapping, I have something that looks like
<sql-query name="spLogin">
<return class="User" />
EXEC dbo.spLogin :username, :password
</sql-query>
The issue is that spLogin doesn't return all of the properties of the User entity. If one of the properties is missing, nHibernate throws an IndexOutOfRangeException on the property that doesn't exist in the result set.
Is there a reason why nHibernate can't lazily load this property, if the entity was retrieved as part of a sql-query that didn't return all properties?
16.2.2. Using stored procedures for querying
Have you tried adding <return-property/> elements?
Are the properties you want to lazy-load marked as lazy?
I've been struggling with this same error this morning. It turned out that my return-property elements did not exactly match what came back from the stored proc. Once this was rectified the error went away.

Map a property to the latest entry in NHibernate

Let's say my domain looks like this:
I have an object, Vehicle, that has an OdometerReading property.
An OdometerReading has the Miles & Date (when it was read).
I need to keep a history of all OdometerReadings for the Vehicle in the database, but don't want the entire odometer history to belong to the Vehicle object. What I would like is for the OdometerReading property map to the most recent OdometerReading entry out of the database.
I thought about mapping the whole collection of OdometerReadings to the Vehicle, and having a dynamic property called CurrentOdometerReading that would order them and return the latest one, but I don't need the whole collection under the Vehicle in my domain, and it seems like I would be getting more data out of the database than I need.
Is that possible with NHibernate? How would I map such a thing?
There are a few ways of doing this depending on what you want your domain model to look like. My preferred choice is to use a custom collection type, for example IOdometerReadingCollection, which you can add extra methods to. In this case it might be something like:
public interface IOdometerReadingCollection : IList<OdometerReading>
{
OdometerReading Latest { get; }
}
This way you can do:
OdometerReading reading = vehicle.OdometerReadings.Latest;
which I prefer to:
OdometerReading reading = vehicle.LatestOdometerReading;
There's lots of documentation about custom collections, which you can find with a simple google search.
If this approach isn't for you there are other options. You may be able to use a property with a formula (I'm not sure if that works with complex types?), or a regular NHibernate association where you'd have the key of the latest OdometerReading on your Vehicle mapping. As you also mentioned you could just load all the OdometerReadings, which depending on your use case might actually be fine.
I hope this helps, or at least points you in the right direction.
There is a "where" clause that you can put in your collection mapping. Check the reference documentation.
I would map the OdometerReading property as a component, then use a named query to ensure it's populated with the latest reading out of the database. (In this example, you'd have a sql-query with a name of "vehicle" that does the SQL to load the Vehicle columns along with the latest Odometer reading)
<class name="Vehicle">
<property name="Type" not-null="true"/>
<component name="OdometerReading">
<property name="Miles" />
<property name="Date" />
</component>
<loader query-ref="vehicle"/>
</class>

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.