I currently have an issue when updating a component collection on an entity. It was originally mapped as a bag but that was causing all entries to be deleted and reinserted each time. Changing it to a set has fixed that problem but introduced a new one.
The component type is called Tracking
it has a composite key of UserID
and ItemID
and two properties which are nullable dates. When one of these is created DateRead
set to the current time, it is then replaced later with an entry with the new date on.
The underlying SQL NHibernate generates has a where clause which checks that all properties match.
The issue is, the other date DateAcknowledged
is often null, and the generated SQL seems to have a syntax error, to do a null check its doing this: = NULL
rather than: IS NULL
, as shown:
DELETE FROM TrackingTable
WHERE ItemId = 'a68f6dea-1c00-42e2-bc40-9fcf01121bd8' /* @p0 */
AND UserId = 'c8aa41a4-e4c2-4347-ae6e-b48738a53b47' /* @p1 */
AND DateRead = '2012-01-26T12:56:46.00' /* @p2 */
AND DateAcknowledged = NULL /* @p3 */
The thing is, the two dates should not be needed at all to determine what to delete. Simply having the where check item ID and user ID would do.
Here is the mapping code where I define the set:
Set(x => x.Trackings,
mapper =>
{
mapper.Key(k => k.Column("ItemId"));
mapper.Table("Tracking");
mapper.Access(Accessor.NoSetter);
},
collectionMapping => collectionMapping.Component(TrackingMap.Mapping()));
And here is the mapping for the component:
public class TrackingMap
{
public static Action<IComponentElementMapper<Tracking>> Mapping()
{
return c =>
{
c.ManyToOne(x => x.User, a => { a.Column("UserId"); a.ForeignKey("UserId"); });
c.Property(x => x.DateRead);
c.Property(x => x.DateAcknowledged, a => a.NotNullable(false));
};
}
}
Is there a way to tell NHibernate to use the keys only on the where clause or for it to compare nulls in the correct way?
This is covered by section 7.2. Collections of dependent objects which notes that this is not supported: