Hello folks, I'd like to solicit your opinion on an approach I've taken to
implement Linq queries on subclass-mapped entities.
I am using the latest NHibernate 3.0 RC (built from SVN)

Here's my domain:

public abstract class Achievement
{
public virtual string id { get; set; }
public virtual string userId { get; set; }
*public virtual string type { get; set; }*
*public virtual string achievementType { get; set; }*

public Achievement() {
achievementType = GetType().Name;
}

public abstract void Combine(Achievement other);
}

public class CouponCountAchievement : Achievement
{
public virtual int purchasedCouponCount { get; set; }

public override void Combine(Achievement other) {
if(typeof(CouponCountAchievement) != other.GetType())
throw new ArgumentOutOfRangeException("other", other.GetType(), "Can't
combine this achievement with CouponCountAchievement");
var otherA = (CouponCountAchievement) other;

purchasedCouponCount += otherA.purchasedCouponCount;
}
}

Note the *bold italic property*: it's the discriminator-value column, while
the* bold property* is a queryable property. Here's the mapping:

public class AchievementMap : ClassMap<Achievement>
{
public AchievementMap() {
Id(x => x.id)
.GeneratedBy.UuidHex("");
Map(x => x.userId);
Map(x => x.achievementType);

DiscriminateSubClassesOnColumn("type");
}
}

public class CouponCountAchievementMap : SubclassMap<CouponCountAchievement>
{
public CouponCountAchievementMap() {
Map(x => x.purchasedCouponCount);
}
}

Here's my query (it works, yeah -- finally solved at 2am local time, after
trying hql and detached criteria :) )

public void RecordAchievement(Achievement achievement, string playerId) {
var session = _container.Resolve<ISession>();
var q = session.Query<Achievement>()
.Where(a =>
       a.achievementType == achievement.achievementType &&
       a.userId == playerId);

var baseAchievement = q.FirstOrDefault() ?? achievement;

baseAchievement.userId = playerId;
session.SaveOrUpdate(baseAchievement);
}

You may wonder what the problem is. Well, simple as cake: I have to
duplicate 'type' and 'achievementType' because I *can't run Linq queries on
'type'*! In order to see why, make the following changes to the above code:

   1. Remove 'achievementType' from Achievement
   2. Change the mapping in AchievementMap to map 'type' instead of
   'achievementType'
   3. Change the query to query on 'type' instead of 'achievementType'
   4. Run and observe the following exception at the end of the message.

I really don't know whether this is an intended behavior or a bug,  but in
any case it should be somehow preventable because the exception itself
doesn't bear any relationship to the real problem with the above code.

System.ArgumentOutOfRangeException : Index was out of range. Must be
non-negative and less than the size of the collection.

Parameter name: index

at System.ThrowHelper.ThrowArgumentOutOfRangeException()

at System.Collections.Generic.List`1.get_Item(Int32 index)

at Npgsql.NpgsqlParameterCollection.get_Item(Int32 index) in
C:\projects\Npgsql2\src\Npgsql\NpgsqlParameterCollection.cs: line 117

at Npgsql.NpgsqlParameterCollection.GetParameter(Int32 index) in
C:\projects\Npgsql2\src\Npgsql\NpgsqlParameterCollection.cs: line 494

at System.Data.Common.DbParameterCollection.
System.Collections.IList.get_Item(Int32 index)

at NHibernate.Type.AbstractStringType.Set(IDbCommand cmd, Object value,
Int32 index) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Type\AbstractStringType.cs:
line 
17<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CType%5CAbstractStringType.cs%3F17%3F1>

at NHibernate.Type.NullableType.NullSafeSet(IDbCommand cmd, Object value,
Int32 index) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Type\NullableType.cs:
line 
180<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CType%5CNullableType.cs%3F180%3F1>

at NHibernate.Type.NullableType.NullSafeSet(IDbCommand st, Object value,
Int32 index, ISessionImplementor session) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Type\NullableType.cs:
line 
139<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CType%5CNullableType.cs%3F139%3F1>

at NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id,
Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][]
includeColumns, Int32 table, IDbCommand statement, ISessionImplementor
session, Int32 index) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:
line 
2415<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CPersister%5CEntity%5CAbstractEntityPersister.cs%3F2415%3F1>

at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id,
Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object
 obj, ISessionImplementor session) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:
line 
2665<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CPersister%5CEntity%5CAbstractEntityPersister.cs%3F2665%3F1>

at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id,
Object[] fields, Object obj, ISessionImplementor session) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:
line 
3015<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CPersister%5CEntity%5CAbstractEntityPersister.cs%3F3015%3F1>

at NHibernate.Action.EntityInsertAction.Execute() in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Action\EntityInsertAction.cs:
line 
59<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CAction%5CEntityInsertAction.cs%3F59%3F1>

at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Engine\ActionQueue.cs:
line 
136<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CEngine%5CActionQueue.cs%3F136%3F1>

at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Engine\ActionQueue.cs:
line 
126<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CEngine%5CActionQueue.cs%3F126%3F1>

at NHibernate.Engine.ActionQueue.ExecuteActions() in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Engine\ActionQueue.cs:
line 
169<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CEngine%5CActionQueue.cs%3F169%3F1>

at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(
IEventSource session) in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:
line 
241<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CEvent%5CDefault%5CAbstractFlushingEventListener.cs%3F241%3F1>

at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs:
line 
19<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CEvent%5CDefault%5CDefaultFlushEventListener.cs%3F19%3F1>

at NHibernate.Impl.SessionImpl.Flush() in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Impl\SessionImpl.cs:
line 
1479<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CImpl%5CSessionImpl.cs%3F1479%3F1>

at NHibernate.Transaction.AdoTransaction.Commit() in
C:\_Projects\KupiKupon\kupikupon-server\lib-src\nhibernate\src\NHibernate\Transaction\AdoTransaction.cs:
line 
187<about:file%3AC%3A%5C_Projects%5CKupiKupon%5Ckupikupon-server%5Clib-src%5Cnhibernate%5Csrc%5CNHibernate%5CTransaction%5CAdoTransaction.cs%3F187%3F1>

*
*

at net.maygem.kupikupon.tests.AchievementTests.
RecordFirstAchievementShouldCreateANewEntryInDB() in
AchievementTests.cs: line 55


<about:projectfile%3AF0D00249-84B1-4394-8AEC-CABA6A4FFA3C%2Fd%3A%23tests%2Ff%3AAchievementTests.cs%3F55%3F1>

-- 
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en.

Reply via email to