问题
I just recently upgraded to FluentNHibernate 1.2 which uses NHibernate 3.1. After upgrading some of my old mappings are not working. I've been having a hard time figuring out why, I thought maybe someone here could help.
I have 3 classes, Practice, Drill, and PracticeDrill. A Practice has many Drills and a Drill can be in many Practices. PracticeDrill is the table that joins them and also includes an Order. Here are my C# POCOs:
public class PracticeDrill
{
public virtual Practice Practice { get; set; }
public virtual Drill Drill { get; set; }
public virtual int Order { get; set; }
}
public class Practice
{
public virtual Guid Id { get; set; }
public virtual ICollection<PracticeDrill> Drills { get; set; }
public Practice()
{
Drills = new List<PracticeDrill>();
}
}
public class Drill
{
public virtual Guid Id { get; set; }
}
Here is what my mapping files look like:
public class PracticeDrillMap : ClassMap<PracticeDrill>
{
public PracticeDrillMap()
{
CompositeId()
.KeyReference(x => x.Practice, "PracticeId")
.KeyReference(x => x.Drill, "DrillId");
Map(x => x.Order)
.Column("[Order]")
.Not.Nullable();
}
}
public class PracticeMap : ClassMap<Practice>
{
public PracticeMap()
{
Id(x => x.Id)
.GeneratedBy.GuidComb();
HasMany(x => x.Drills)
.KeyColumn("PracticeId")
.AsBag()
.Inverse()
.Cascade.AllDeleteOrphan();
}
}
public class DrillMap : ClassMap<Drill>
{
public DrillMap()
{
Id(x => x.Id)
.GeneratedBy.GuidComb();
}
}
This previously allowed me to Create/Delete Practices that referenced Drills. Now when I try to Delete a practice I get the following exception:
{System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.ThrowHelper.ThrowKeyNotFoundException() at System.Collections.Generic.Dictionary`2.get_Item(TKey key) at NHibernate.Engine.StatefulPersistenceContext.RemoveEntity(EntityKey key) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\StatefulPersistenceContext.cs:line 444 at NHibernate.Action.EntityDeleteAction.Execute() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Action\EntityDeleteAction.cs:line 87 at NHibernate.Engine.ActionQueue.Execute(IExecutable executable) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:line 136 at NHibernate.Engine.ActionQueue.ExecuteActions(IList list) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:line 126 at NHibernate.Engine.ActionQueue.ExecuteActions() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\ActionQueue.cs:line 174 at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\AbstractFlushingEventListener.cs:line 241 at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Event\Default\DefaultFlushEventListener.cs:line 19 at NHibernate.Impl.SessionImpl.Flush() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 1472 at NHibernate.Transaction.AdoTransaction.Commit() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Transaction\AdoTransaction.cs:line 187 at GoldMedalSquared.Toolbox.Data.NHibernate.RepositoryBase`1.WrapInTransaction(ISession session, Action query) in C:\Work\primary\trunk\Toolbox\Data.NHibernate\RepositoryBase.cs:line 42}
Any suggestions?
回答1:
You mapped ICollection<PracticeDrill> Drills
with only one foreign key (.KeyColumn("PracticeId")
), but it actually has a composite key. Therefore NH can't fine the PracticeDrill
by its id.
The whole mapping is a bit strange. Why using a reference class? If it is really necessary, why using a composite key?
来源:https://stackoverflow.com/questions/6977167/nhibernate-mapping-breaks-when-upgrading-to-nhibernate-3-1